Time registrationsValidate a time registration import

Validate a time registration import

Checks whether an import body would be accepted, without saving the registration.

Runs the import's existence checks (project, contract-on-project, task-on-contract, active user) and the time-registration business rules, then returns an empty success. It is stricter than import itself, which skips the existence checks. It is NOT side-effect free: the employee may be allocated to the task.

Use it to:

  • Pre-flight a migration batch before calling import

Not for:

  • Checking rates — HourlyRate is not evaluated (no rate lookup or swap is simulated, so 38037 cannot be pre-flighted)

Rules across fields:

  • R1: Same as import R1–R3.
  • R2: GroupType ≠ Absence → ProjectID must exist, ContractID must belong to ProjectID, TaskID must be on ContractID.

Behaviour:

  • Idempotent.
  • Safe to retry.
  • Side effect: If the employee is not allocated to TaskID: adds the employee to the project resource group and contract team and creates a 0-hour allocation. This persists.
  • Read-after-write consistency: not yet documented.

Next: POST /v1/time-registration/import

Not yet documented: behaviour → consistency; examples (success).

curl -X POST "https://app3.timelog.com/your-account/api/v1/time-registration/validate-import" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
  "TaskID": 123,
  "ProjectID": 123,
  "ContractID": 123,
  "UserID": 123,
  "Date": "2024-12-25T10:00:00Z",
  "Hours": 3.14,
  "GroupType": 42,
  "AbsenceCodeID": 123,
  "Billable": true,
  "Comment": "example_string",
  "AdditionalComment": "example_string",
  "BillableHours": 3.14,
  "MonthlyPeriod": "example_string",
  "HourlyRate": 3.14,
  "HourlyRateName": "John Doe",
  "CostPrice": 29.99,
  "CostPriceName": "John Doe"
}'
"null"
POST
/v1/time-registration/validate-import
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
TaskIDinteger

The task the time is registered on. Determines the allocation (and so the contract actually used). Conditional. Required (non-zero) unless GroupType = Absence (3). Refers to TaskRead.TaskID. - GroupType = Project or TravelTime — If the employee is not allocated to the task, the allocation is CREATED (staffing side effect, see operation). Import does NOT check that TaskID belongs to ContractID/ProjectID (only validate-import does). > Not yet documented: values → lookup op.

Format: int32
ProjectIDinteger

The project. On import it is only used to pick the currency of a newly created hourly rate. Conditional. Required (non-zero) unless GroupType = Absence (3). Refers to ProjectRead.ProjectID. > Not yet documented: values → lookup op.

Format: int32
ContractIDinteger

The project contract (sub-contract) on which the import's project-specific hourly rate is found or created. Conditional. Required (non-zero) unless GroupType = Absence (3). Refers to ContractRead.ContractID. > Not yet documented: values → lookup op.

Format: int32
UserIDinteger
Required

The user (employee) the time belongs to. Refers to UserRead.UserID. - UserID is not the caller and the caller lacks RegistrationAllRegistrations — Fails with 300131 (HTTP 500). Department / legal-entity access does not count on this path. > Not yet documented: values → lookup op.

Format: int32
Datestring
Required

The date the time is registered on. Time zone: not yet documented. > Not yet documented: constraints → timezone.

Format: date-time
Hoursnumber
Required

Duration in decimal hours. Unit: hours (decimal) Required and non-zero for every GroupType, including absence. TimeTrackingFormat is always Hours on import.

Format: double
GroupTypeinteger
Required

What kind of registration this is. The validator's NotNull rule cannot fail on a non-nullable enum: an omitted GroupType arrives as 0 and is treated as a non-absence registration. Allowed values: | Value | Name | Meaning | |---|---|---| | 1 | Project | Time worked on a project task. | | 3 | Absence | Absence. AbsenceCodeID is required; Project/Contract/Task are not. | | 6 | TravelTime | Travel time on a project task. | > Not yet documented: notes.

Options: 1, 3, 6
AbsenceCodeIDinteger

For absence, the absence code to register. Conditional. Required (non-zero) when GroupType = Absence (3); must be 0/omitted otherwise (validation error). Refers to AbsenceCodeRead.AbsenceCodeID. > Not yet documented: values → lookup op.

Format: int32
Billableboolean

Whether the time is billable. Same account-feature overrides as TimeRegistrationWrite.Billable (BillableFlagCoordinator).

Commentstring

Free-text comment on the registration.

AdditionalCommentstring

Second free-text field, configurable per site. Conditional. Required when the site configures the additional field as mandatory (30048).

BillableHoursnumber

Billable duration in decimal hours. Unit: hours (decimal)

Format: double
MonthlyPeriodstring

Salary month the registration belongs to (MMyyyy). Same rules as TimeRegistrationWrite.MonthlyPeriod (malformed → HTTP 500).

HourlyRatenumber

Hourly rate to price this registration with. Unit: currency per hour — the project's currency Contains financial data. - GroupType = Project or TravelTime and value differs from the allocation's current rate — An active project-specific hourly rate on ContractID with the same name (HourlyRateName, case-insensitive) and amount is reused; otherwise a new one is created and persists. The allocation points at it for the save and is pointed back afterwards (also on failure). The value is non-nullable: omitting it means 0, which prices the registration at 0 when HourlyRateName is given and fails with 38037 when it is not (unless the allocation's rate is 0). - GroupType = Project or TravelTime and value equals the allocation's current rate — No rate is created; the allocation's rate applies. - GroupType = Absence — ignored Not evaluated by the manager (only by the 400 validator rule R3 of import).

Format: double
HourlyRateNamestring

Name of the project-specific hourly rate to reuse or create for this import. Conditional. Required when GroupType is not Absence and HourlyRate ≠ 0 (400), and when HourlyRate differs from the allocation's current rate (38037, HTTP 500). Only the validator rule applies (required when HourlyRate ≠ 0 for non-absence); the 38037 check of import does not run.

CostPricenumber

Obsolete. Formerly the employee cost price for this registration. Contains financial data. Ignored (obsolete). > Not yet documented: constraints → unit.

Format: double
CostPriceNamestring

Obsolete. Formerly the name of the employee cost rate to use or create. Ignored (obsolete).

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
TaskIDinteger

The task the time is registered on. Determines the allocation (and so the contract actually used).

Conditional. Required (non-zero) unless GroupType = Absence (3).

Refers to TaskRead.TaskID.

  • GroupType = Project or TravelTime — If the employee is not allocated to the task, the allocation is CREATED (staffing side effect, see operation).

Import does NOT check that TaskID belongs to ContractID/ProjectID (only validate-import does).

Not yet documented: values → lookup op.

ProjectIDinteger

The project. On import it is only used to pick the currency of a newly created hourly rate.

Conditional. Required (non-zero) unless GroupType = Absence (3).

Refers to ProjectRead.ProjectID.

Not yet documented: values → lookup op.

ContractIDinteger

The project contract (sub-contract) on which the import's project-specific hourly rate is found or created.

Conditional. Required (non-zero) unless GroupType = Absence (3).

Refers to ContractRead.ContractID.

Not yet documented: values → lookup op.

UserIDinteger
Required

The user (employee) the time belongs to.

Refers to UserRead.UserID.

  • UserID is not the caller and the caller lacks RegistrationAllRegistrations — Fails with 300131 (HTTP 500). Department / legal-entity access does not count on this path.

Not yet documented: values → lookup op.

Datestring
Required

The date the time is registered on.

Time zone: not yet documented.

Not yet documented: constraints → timezone.

Hoursnumber
Required

Duration in decimal hours.

Unit: hours (decimal)

Required and non-zero for every GroupType, including absence. TimeTrackingFormat is always Hours on import.

GroupTypeinteger
Required

What kind of registration this is.

The validator's NotNull rule cannot fail on a non-nullable enum: an omitted GroupType arrives as 0 and is treated as a non-absence registration.

Allowed values:

ValueNameMeaning
1ProjectTime worked on a project task.
3AbsenceAbsence. AbsenceCodeID is required; Project/Contract/Task are not.
6TravelTimeTravel time on a project task.

Not yet documented: notes.

Allowed values:136
AbsenceCodeIDinteger

For absence, the absence code to register.

Conditional. Required (non-zero) when GroupType = Absence (3); must be 0/omitted otherwise (validation error).

Refers to AbsenceCodeRead.AbsenceCodeID.

Not yet documented: values → lookup op.

Billableboolean

Whether the time is billable.

Same account-feature overrides as TimeRegistrationWrite.Billable (BillableFlagCoordinator).

Commentstring

Free-text comment on the registration.

AdditionalCommentstring

Second free-text field, configurable per site.

Conditional. Required when the site configures the additional field as mandatory (30048).

BillableHoursnumber

Billable duration in decimal hours.

Unit: hours (decimal)

MonthlyPeriodstring

Salary month the registration belongs to (MMyyyy).

Same rules as TimeRegistrationWrite.MonthlyPeriod (malformed → HTTP 500).

HourlyRatenumber

Hourly rate to price this registration with.

Unit: currency per hour — the project's currency

Contains financial data.

  • GroupType = Project or TravelTime and value differs from the allocation's current rate — An active project-specific hourly rate on ContractID with the same name (HourlyRateName, case-insensitive) and amount is reused; otherwise a new one is created and persists. The allocation points at it for the save and is pointed back afterwards (also on failure). The value is non-nullable: omitting it means 0, which prices the registration at 0 when HourlyRateName is given and fails with 38037 when it is not (unless the allocation's rate is 0).

  • GroupType = Project or TravelTime and value equals the allocation's current rate — No rate is created; the allocation's rate applies.

  • GroupType = Absence — ignored

Not evaluated by the manager (only by the 400 validator rule R3 of import).

HourlyRateNamestring

Name of the project-specific hourly rate to reuse or create for this import.

Conditional. Required when GroupType is not Absence and HourlyRate ≠ 0 (400), and when HourlyRate differs from the allocation's current rate (38037, HTTP 500).

Only the validator rule applies (required when HourlyRate ≠ 0 for non-absence); the 38037 check of import does not run.

CostPricenumber

Obsolete. Formerly the employee cost price for this registration.

Contains financial data.

Ignored (obsolete).

Not yet documented: constraints → unit.

CostPriceNamestring

Obsolete. Formerly the name of the employee cost rate to use or create.

Ignored (obsolete).

Responses

Success without content: HTTP 200 with the literal JSON body null. Body is the literal JSON null: the import would be accepted.