Users and organisationCreate a user

Create a user

Creates an active user (employee) with its HR settings and returns it.

Creates the login and the employee profile in one call: name, initials, e-mail, legal entity, department, approval manager, rates, calendar, working time, salary group, licence type and extra roles. The new user is active immediately; time zone, language and front page come from account defaults. Run POST /v1/user/validate-new-user first to get every rule violation without side effects. The response is the User representation, which does not echo most of what was sent.

Use it to:

Not for:

  • Changing an existing user → PUT /v1/user (name, licence, roles, approval manager only)

Rules across fields:

  • R1: UserRoleIDs must be null or empty unless UserLicenseType is Standard (2).
  • R2: StandardHourlyRateID and CostPriceID must belong to LegalEntityID.
  • R3: Neither UserName nor Initials may be used by another user, active or inactive.

Behaviour:

  • Not idempotent.
  • Safe to retry only under a condition. A retry after a timeout fails with 20022 if the first call succeeded — check user.list for the initials before retrying.
  • Duplicates: UserName and Initials must be unused (application check, 20022/20024); nothing else is deduplicated.
  • Side effect: Inserts the user, its profile, its personal (employee-specific) role and the licence's system role or the requested roles, default page settings and predefined filter views
  • Side effect: Sets an initial login credential for the user
  • Side effect: Creates the cost-price drill-down rows and refreshes the platform licence status
  • Side effect: Updates the allocation-search denormalisation (a failure here is logged and ignored)
  • On failure: When the insert fails after the user row is written, the call returns 500 Code 100 and the partial user may remain
  • Changes are visible to the next read immediately.

Call first: GET /v1/legal-entity, GET /v1/department, POST /v1/user/validate-new-user

Next: GET /v1/user/{id}, PUT /v1/user

Not yet documented: behaviour → events emitted; behaviour → side effects; examples.

curl -X POST "https://app3.timelog.com/your-account/api/v1/user/create" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
  "UserName": "John Doe",
  "FirstName": "John Doe",
  "LastName": "John Doe",
  "Initials": "example_string",
  "Email": "user@example.com",
  "Title": "example_string",
  "EmployeeNo": "example_string",
  "EmploymentDate": "2024-12-25T10:00:00Z",
  "LegalEntityID": 123,
  "DepartmentID": 123,
  "ApprovalManagerID": 123,
  "EmployeeTypeID": 123,
  "StandardHourlyRateID": 123,
  "CostPriceID": 123,
  "PublicHolidayCalendarID": 123,
  "AllowanceLegislationID": 123,
  "NormalWorkingTimeID": 123,
  "SalaryGroupID": 123,
  "UserLicenseType": 42,
  "UserRoleIDs": [
    "null"
  ]
}'
{
  "Properties": {
    "UserID": 123,
    "ID": "123e4567-e89b-12d3-a456-426614174000",
    "FirstName": "John Doe",
    "LastName": "John Doe",
    "Initials": "example_string",
    "IsActive": true,
    "UserType": "Employee",
    "LegalEntityID": 123,
    "Email": "user@example.com"
  },
  "Links": [
    {
      "Href": "example_string",
      "Rel": "example_string"
    }
  ],
  "Actions": [
    {}
  ]
}
POST
/v1/user/create
POST
Base URLstring

Target server for requests. Edit to use your own host.

Bearer Token
Bearer Tokenstring
Required

OAuth 2.0 bearer token, sent as Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp). The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user. > Not yet documented: how to obtain a token. > Not yet documented: token lifetime.

OAuth 2.0 bearer token, sent as Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp). The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user. > Not yet documented: how to obtain a token. > Not yet documented: token lifetime.
Content-Typestring
Required

The media type of the request body

Options: application/json
UserNamestring
Required

Login name of the new user. Not returned by any REST v1 read. Can be set on create only. Alternate key, unique per TimeLog site. Contains personal data. - Same user name or initials as an active user — 20022 (business rule, HTTP 500). - Same user name or initials as an inactive user — 20024 (business rule, HTTP 500). Create never reuses an inactive user's name.

Max length: 50
FirstNamestring
Required

First name. Can be set on create only. Contains personal data.

Max length: 50
LastNamestring
Required

Last name. Can be set on create only. Contains personal data.

Max length: 50
Initialsstring
Required

Short handle of the user (see User.Initials). Must not be used by another user (active: 20022, inactive: 20024). Can be set on create only. Alternate key, unique per TimeLog site. Contains personal data.

Max length: 50
Emailstring
Required

E-mail address. Can be set on create only. Contains personal data. - Empty or not an e-mail address — 400 Code 200 ('Email' must not be empty / The specified condition was not met for 'Email'). - Passes the model check but fails the business-rule format check — 31114 (business rule, HTTP 500).

Format: email • Max length: 255
Titlestring

Job title. Can be set on create only. Contains personal data.

Max length: 50
EmployeeNostring

Employee number. Conditional. Required when the account feature ShowEmployeeID is on (31027, business rule, HTTP 500); optional otherwise. Can be set on create only. Key from your own system, unique per TimeLog site. Uniqueness is not enforced. Contains personal data.

Max length: 200
EmploymentDatestring
Required

First day of employment. Can be set on create only. Time zone: not yet documented. Contains personal data. - Year not valid — 31029 (business rule, HTTP 500). > Not yet documented: constraints → timezone.

Format: date-time
LegalEntityIDinteger
Required

Legal entity the user is employed in. Can be set on create only. Refers to LegalEntityRead.LegalEntityID. Look up valid values with GET /v1/legal-entity. - Feature MultiLegalEntities on and the ID does not exist — 37029 (business rule, HTTP 500). - Feature MultiLegalEntities off and the ID is not the system legal entity — 37921 (business rule, HTTP 500). Use GET /v1/legal-entity/system. Valid values come from GET /v1/legal-entity.

DepartmentIDinteger
Required

Department the user belongs to. Inactive departments are accepted. Can be set on create only. Refers to DepartmentRead.DepartmentID. Look up valid values with GET /v1/department. - The ID does not exist — 37039 (business rule, HTTP 500). Valid values come from GET /v1/department.

ApprovalManagerIDinteger

User ID (not employee ID) of the manager who approves this user's time sheets. 0 = no approval manager. Can be set on create only. Refers to UserRead.UserID. Look up valid values with GET /v1/user. - Non-zero and not an existing user — 37038 (business rule, HTTP 500). Valid values come from GET /v1/user.

EmployeeTypeIDinteger

Employee type (account-defined category). 0 = none. Can be set on create only. Refers to EmployeeTypeRead.EmployeeTypeID. - Non-zero and not an existing employee type — 37028 (business rule, HTTP 500). Valid values come from GET /v1/role. > Not yet documented: values → lookup op.

StandardHourlyRateIDinteger
Required

Standard hourly (sales) rate of the user; must belong to the user's legal entity. Can be set on create only. Refers to HourlyRateRead.HourlyRateID. Look up valid values with GET /v1/hourly-rate. - 0 — 400 'Standard Hourly Rate ID' must not be empty. - Negative — Replaced by the legal entity's system default hourly rate. - Positive and not an existing rate / not a rate of LegalEntityID — 37030 / 37031 (business rule, HTTP 500). GET /v1/hourly-rate returns the price-list entries of ALL legal entities (incl. customer lists); pick an entry with CustomerID null and LegalEntityID = the user's legal entity. Valid values come from GET /v1/hourly-rate.

CostPriceIDinteger
Required

Cost price group of the user; must belong to the user's legal entity. Can be set on create only. Refers to CostPriceRead.CostPriceID. Look up valid values with GET /v1/cost-price. - Not an existing cost price / not one of LegalEntityID — 37032 / 37051 (business rule, HTTP 500). GET /v1/cost-price returns the cost price groups of ALL legal entities; pick one with LegalEntityId = the user's legal entity. Valid values come from GET /v1/cost-price.

PublicHolidayCalendarIDinteger
Required

Public-holiday calendar that drives the user's non-working days. Can be set on create only. Refers to HolidayCalendarRead.HolidayCalendarID. - Not an existing calendar — 37033 (business rule, HTTP 500). > Not yet documented: values → lookup op.

AllowanceLegislationIDinteger
Required

Allowance (per-diem) legislation that applies to the user's travel expenses. Can be set on create only. Refers to AllowanceLegislationRead.AllowanceLegislationID. Look up valid values with GET /v1/allowance-legislation. - Not an existing legislation — 37034 (business rule, HTTP 500). Valid values come from GET /v1/allowance-legislation.

NormalWorkingTimeIDinteger
Required

Normal working time (weekly norm) of the user. Also stored as the user's work week. Can be set on create only. Refers to NormalWorkingTimeRead.NormalWorkingTimeID. - Not an existing normal working time — 37035 (business rule, HTTP 500). - Account on an edition that allows only the default normal working time — 37923 (business rule, HTTP 500). > Not yet documented: values → lookup op.

SalaryGroupIDinteger
Required

Salary group of the user. Can be set on create only. Refers to SalaryGroupRead.SalaryGroupID. - Feature SalaryGroups on and the group does not exist / is inactive — 37036 / 37925 (business rule, HTTP 500). - Feature SalaryGroups off and the ID is not the system salary group — 37924 (business rule, HTTP 500). Model validation only checks NotNull (never fails on an int); omitting it sends 0, which the business rule rejects in both feature states. > Not yet documented: values → lookup op.

UserLicenseTypeinteger

Licence the user is billed for; decides which functionality the user can reach. Can be set on create only. Allowed values: | Value | Name | Meaning | |---|---|---| | 2 | Standard | Standard user: access to most functionality, depending on the account's licence model. The only value accepted when neither ExternalUserLicense nor TimeExpenseUserLicense is on. | | 7 | Limited | Limited user. Accepted only when feature ExternalUserLicense is on; the system role 'Limited user' is assigned and UserRoleIDs must be empty. | | 8 | TimeExpense | Time and expense tracking with reports. Accepted only when feature TimeExpenseUserLicense is on; the system role 'Time and expense registrations' is assigned and UserRoleIDs must be empty. | | 1 | External | External user (time tracking only). Rejected by this operation. | | 3 | Advanced | Advanced user of special licence models. Rejected by this operation. | | 4 | ExternalPlus | External user with external disbursement. Rejected by this operation. | | 6 | TlpBasicLimited | Limited user of the Basic contract. Rejected by this operation. | | 0 | NotSpecified | No licence (no access). Rejected by this operation. |

Options: 2, 7, 8, 1, 3, 4, 6, 0
UserRoleIDsarray

Additional roles to give the user. Only for Standard (2) users. Conditional. Allowed only when UserLicenseType is Standard (2); must be null or empty otherwise (400). Can be set on create only. Refers to RoleRead.RoleID. Look up valid values with GET /v1/role. > Not yet documented: multiple → max items. > Not yet documented: multiple → duplicates allowed.

Request Preview
Response

Response will appear here after sending the request

Authentication

header
Authorizationstring
Required

Bearer token. OAuth 2.0 bearer token, sent as Authorization: Bearer <token>. JWT and reference tokens are both accepted. The token must carry the required scope (default tlp).

The token's sub claim is the acting user. A token WITHOUT sub (client-credentials) acts as the system service user. If the sub user cannot log in (inactive, locked, deleted), the request is rejected with 401 — it is no longer let through without a user.

Not yet documented: how to obtain a token.

Not yet documented: token lifetime.

Body

application/json
UserNamestring
Required

Login name of the new user. Not returned by any REST v1 read.

Can be set on create only.

Alternate key, unique per TimeLog site.

Contains personal data.

  • Same user name or initials as an active user — 20022 (business rule, HTTP 500).

  • Same user name or initials as an inactive user — 20024 (business rule, HTTP 500). Create never reuses an inactive user's name.

FirstNamestring
Required

First name.

Can be set on create only.

Contains personal data.

LastNamestring
Required

Last name.

Can be set on create only.

Contains personal data.

Initialsstring
Required

Short handle of the user (see User.Initials). Must not be used by another user (active: 20022, inactive: 20024).

Can be set on create only.

Alternate key, unique per TimeLog site.

Contains personal data.

Emailstring
Required

E-mail address.

Can be set on create only.

Contains personal data.

  • Empty or not an e-mail address — 400 Code 200 ('Email' must not be empty / The specified condition was not met for 'Email').

  • Passes the model check but fails the business-rule format check — 31114 (business rule, HTTP 500).

Titlestring

Job title.

Can be set on create only.

Contains personal data.

EmployeeNostring

Employee number.

Conditional. Required when the account feature ShowEmployeeID is on (31027, business rule, HTTP 500); optional otherwise.

Can be set on create only.

Key from your own system, unique per TimeLog site. Uniqueness is not enforced.

Contains personal data.

EmploymentDatestring
Required

First day of employment.

Can be set on create only.

Time zone: not yet documented.

Contains personal data.

  • Year not valid — 31029 (business rule, HTTP 500).

Not yet documented: constraints → timezone.

LegalEntityIDinteger
Required

Legal entity the user is employed in.

Can be set on create only.

Refers to LegalEntityRead.LegalEntityID. Look up valid values with GET /v1/legal-entity.

  • Feature MultiLegalEntities on and the ID does not exist — 37029 (business rule, HTTP 500).

  • Feature MultiLegalEntities off and the ID is not the system legal entity — 37921 (business rule, HTTP 500). Use GET /v1/legal-entity/system.

Valid values come from GET /v1/legal-entity.

DepartmentIDinteger
Required

Department the user belongs to. Inactive departments are accepted.

Can be set on create only.

Refers to DepartmentRead.DepartmentID. Look up valid values with GET /v1/department.

  • The ID does not exist — 37039 (business rule, HTTP 500).

Valid values come from GET /v1/department.

ApprovalManagerIDinteger

User ID (not employee ID) of the manager who approves this user's time sheets. 0 = no approval manager.

Can be set on create only.

Refers to UserRead.UserID. Look up valid values with GET /v1/user.

  • Non-zero and not an existing user — 37038 (business rule, HTTP 500).

Valid values come from GET /v1/user.

EmployeeTypeIDinteger

Employee type (account-defined category). 0 = none.

Can be set on create only.

Refers to EmployeeTypeRead.EmployeeTypeID.

  • Non-zero and not an existing employee type — 37028 (business rule, HTTP 500).

Valid values come from GET /v1/role.

Not yet documented: values → lookup op.

StandardHourlyRateIDinteger
Required

Standard hourly (sales) rate of the user; must belong to the user's legal entity.

Can be set on create only.

Refers to HourlyRateRead.HourlyRateID. Look up valid values with GET /v1/hourly-rate.

  • 0 — 400 'Standard Hourly Rate ID' must not be empty.

  • Negative — Replaced by the legal entity's system default hourly rate.

  • Positive and not an existing rate / not a rate of LegalEntityID — 37030 / 37031 (business rule, HTTP 500).

GET /v1/hourly-rate returns the price-list entries of ALL legal entities (incl. customer lists); pick an entry with CustomerID null and LegalEntityID = the user's legal entity.

Valid values come from GET /v1/hourly-rate.

CostPriceIDinteger
Required

Cost price group of the user; must belong to the user's legal entity.

Can be set on create only.

Refers to CostPriceRead.CostPriceID. Look up valid values with GET /v1/cost-price.

  • Not an existing cost price / not one of LegalEntityID — 37032 / 37051 (business rule, HTTP 500).

GET /v1/cost-price returns the cost price groups of ALL legal entities; pick one with LegalEntityId = the user's legal entity.

Valid values come from GET /v1/cost-price.

PublicHolidayCalendarIDinteger
Required

Public-holiday calendar that drives the user's non-working days.

Can be set on create only.

Refers to HolidayCalendarRead.HolidayCalendarID.

  • Not an existing calendar — 37033 (business rule, HTTP 500).

Not yet documented: values → lookup op.

AllowanceLegislationIDinteger
Required

Allowance (per-diem) legislation that applies to the user's travel expenses.

Can be set on create only.

Refers to AllowanceLegislationRead.AllowanceLegislationID. Look up valid values with GET /v1/allowance-legislation.

  • Not an existing legislation — 37034 (business rule, HTTP 500).

Valid values come from GET /v1/allowance-legislation.

NormalWorkingTimeIDinteger
Required

Normal working time (weekly norm) of the user. Also stored as the user's work week.

Can be set on create only.

Refers to NormalWorkingTimeRead.NormalWorkingTimeID.

  • Not an existing normal working time — 37035 (business rule, HTTP 500).

  • Account on an edition that allows only the default normal working time — 37923 (business rule, HTTP 500).

Not yet documented: values → lookup op.

SalaryGroupIDinteger
Required

Salary group of the user.

Can be set on create only.

Refers to SalaryGroupRead.SalaryGroupID.

  • Feature SalaryGroups on and the group does not exist / is inactive — 37036 / 37925 (business rule, HTTP 500).

  • Feature SalaryGroups off and the ID is not the system salary group — 37924 (business rule, HTTP 500).

Model validation only checks NotNull (never fails on an int); omitting it sends 0, which the business rule rejects in both feature states.

Not yet documented: values → lookup op.

UserLicenseTypeinteger

Licence the user is billed for; decides which functionality the user can reach.

Can be set on create only.

Allowed values:

ValueNameMeaning
2StandardStandard user: access to most functionality, depending on the account's licence model. The only value accepted when neither ExternalUserLicense nor TimeExpenseUserLicense is on.
7LimitedLimited user. Accepted only when feature ExternalUserLicense is on; the system role 'Limited user' is assigned and UserRoleIDs must be empty.
8TimeExpenseTime and expense tracking with reports. Accepted only when feature TimeExpenseUserLicense is on; the system role 'Time and expense registrations' is assigned and UserRoleIDs must be empty.
1ExternalExternal user (time tracking only). Rejected by this operation.
3AdvancedAdvanced user of special licence models. Rejected by this operation.
4ExternalPlusExternal user with external disbursement. Rejected by this operation.
6TlpBasicLimitedLimited user of the Basic contract. Rejected by this operation.
0NotSpecifiedNo licence (no access). Rejected by this operation.
Allowed values:27813460
UserRoleIDsarray

Additional roles to give the user. Only for Standard (2) users.

Conditional. Allowed only when UserLicenseType is Standard (2); must be null or empty otherwise (400).

Can be set on create only.

Refers to RoleRead.RoleID. Look up valid values with GET /v1/role.

Not yet documented: multiple → max items.

Not yet documented: multiple → duplicates allowed.

Responses

Propertiesobject

A TimeLog user as REST v1 returns it: identifiers, name, initials, e-mail, active flag, user type and legal entity. In TimeLog a user and an employee are the same person seen from two sides: the user is the login, the employee record carries the HR data.

Linksarray
Actionsobject[]