ProjectsCreate a task on a project

Create a task on a project

Adds a root task to a project's plan and returns it.

Creates a task at the next top-level position of the project's work breakdown structure, on the contract you name (default: the project's main contract), with its budget and hourly rate; for task-driven-revenue (TDR) contracts also its payment settings. Answers 200 with the new task as TaskRead. Not idempotent and not atomic. No project privilege is checked. An empty or half-filled body answers 500 Code 100 instead of a 400 field list: always send ProjectID, TaskName, StartDate, EndDate, BudgetHours, BudgetAmount and HourlyRateID.

Use it to:

  • Create the task structure of a project created from an external system (ERP / CRM project sync)
  • Add a task for a new deliverable before people register time on it

Not for:

  • A task under an existing task → POST /v1/task/create-sub-task
  • A dry run → POST /v1/task/validate-new-task

Rules across fields:

  • R1: Time & material contract: BudgetHours, BudgetAmount and HourlyRateID may not ALL be non-zero (one is derived from the other two). 400 with one message per field.
  • R2: TDR contract: BudgetHours, BudgetAmount and TaskHourlyRate may not ALL be non-zero (400).
  • R3: TDR contract: TaskHourlyRate must be 0 when HourlyRateID is not 0 (400).
  • R4: TDR contract: PaymentRecognitionModel must be 1 or 2; with 2 (FixedPricePayment) PaymentProductNo, PaymentName and PaymentInvoiceDate are required (400).
  • R5: EndDate must be on or after StartDate (400).

Behaviour:

  • Not idempotent.
  • Not safe to retry blindly. Every call inserts a new task; there is no external key or dedup. After a timeout or a 500, list the project's tasks (GET /v1/task) before retrying.
  • Side effect: TDR + FixedPricePayment, or a time-and-material-basic contract: if the task then has exactly one instalment, sets its name / invoice date / product number / amount (TDR: PaymentAmount; TMB: the task budget amount) and IsReadyForInvoicing, and saves the billing plan.
  • Side effect: Re-saves the project: the project row is updated, project dates may be aligned to the task plan, invoicing potential is recalculated.
  • On failure: The task, its events and the project re-save are committed before MapTDRTaskWithPayment; a failure there answers 500 while the task stays.
  • Changes are visible to the next read immediately.

Call first: GET /v1/project/get-all, GET /v1/contract

Next: GET /v1/task/{taskID}, POST /v1/task/create-sub-task

See also: POST /v1/task/validate-new-task

Not yet documented: behaviour → side effects; examples; request → body.

curl -X POST "https://app3.timelog.com/your-account/api/v1/task" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
  "ProjectID": 123,
  "ParentTaskID": "null",
  "TaskName": "John Doe",
  "TaskNo": "null",
  "Description": "null",
  "StartDate": "2024-12-25T10:00:00Z",
  "EndDate": "2024-12-25T10:00:00Z",
  "AdditionalTextIsRequired": true,
  "IsBillable": true,
  "IsReadyForInvoicing": true,
  "ProjectSubContractID": "null",
  "HourlyRateID": 123,
  "BudgetHours": 3.14,
  "BudgetAmount": 3.14,
  "TaskTypeID": "null",
  "PaymentRecognitionModel": 42,
  "PaymentAmount": 3.14,
  "TaskHourlyRate": 3.14,
  "PaymentProductNo": "null",
  "PaymentName": "null",
  "PaymentInvoiceDate": "null"
}'
{
  "Properties": {
    "TaskID": 123,
    "ID": "123e4567-e89b-12d3-a456-426614174000",
    "Name": "John Doe",
    "No": "example_string",
    "IsFixedPrice": true,
    "IsDefaultBillable": true,
    "AdditionalTextIsRequired": true,
    "ParentFullName": "John Doe",
    "ProjectID": 123,
    "Project": {
      "ProjectID": 123,
      "ID": "123e4567-e89b-12d3-a456-426614174000",
      "Name": "John Doe",
      "No": "example_string",
      "ExpenseIsBillable": "null",
      "CustomerID": 123,
      "Customer": {
        "CustomerID": 123,
        "ID": "123e4567-e89b-12d3-a456-426614174000",
        "Name": "John Doe",
        "No": "example_string",
        "DefaultMileageDistance": 25,
        "CustomerStatusID": 123,
        "VATNo": "example_string",
        "OrganizationNo": "example_string"
      },
      "MainContractId": 123
    },
    "ParentTaskID": "null",
    "IsTravelTimeTask": true,
    "IsFavourite": "null"
  },
  "Links": [
    {
      "Href": "example_string",
      "Rel": "example_string"
    }
  ],
  "Actions": [
    {}
  ]
}
POST
/v1/task
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
ProjectIDinteger
Required

The project the task is created on. Can be set on create only. Refers to ProjectRead.ProjectID. Look up valid values with GET /v1/project/get-all. - 0 or omitted — Should be 400 'Project ID must be greater than 0', but the validator's contract rules crash first: 500 Code 100. - Unknown ID — 500 Code 102 / 37014 (rest.projectmanagement.project-not-found) — or 500 Code 100 when the validator's contract lookup runs first. Valid values come from GET /v1/project/get-all.

Format: int32
ParentTaskIDintegernull

The existing task the new task is placed under (create-sub-task only). Can be set on create only. Refers to TaskRead.TaskID. Look up valid values with GET /v1/task. - Sent as 0 or negative — 400 (must be > 0 when present). - create-sub-task: the task is on ANOTHER project — The parent is re-resolved by its WBS number inside ProjectID: the sub-task lands under the task of ProjectID that has the same WBS number, or the call fails with 500. - create-sub-task: null — Treated as task 0: 500 rest.projectmanagement.task-not-found (37001). Valid values come from GET /v1/task.

Format: int32
TaskNamestring
Required

Display name of the task. > Not yet documented: constraints → max length.

Min length: 1
TaskNostringnull

The task number shown next to the name (searchable by the time-tracking searches). Copied as sent. > Not yet documented: notes.

Descriptionstringnull

Free-text description of the task.

StartDatestring
Required

Planned start of the task. Time zone: not yet documented. - Omitted (0001-01-01) — 400 'StartDate is not a valid date.' > Not yet documented: constraints → timezone.

Format: date-time
EndDatestring
Required

Planned end of the task. Time zone: not yet documented. - Omitted (0001-01-01) — 400 with the message 'StartDate is not a valid date.'. - Before StartDate — 400 'EndDate must be equal to or greater than StartDate.' - Time-and-material basic contract — Becomes the invoice date of the task's instalment. > Not yet documented: constraints → timezone.

Format: date-time
AdditionalTextIsRequiredboolean

When true, time registrations on this task must carry an additional comment.

IsBillableboolean

Default billable flag of time registered on the task. Omitted = false (non-billable task). Read back as TaskRead.IsDefaultBillable.

IsReadyForInvoicingboolean

Marks the task (and, for TDR fixed-price-payment / time-and-material-basic tasks, its instalment) ready for invoicing.

ProjectSubContractIDintegernull

The contract of the project the task is invoiced on. Refers to ContractRead.ContractID. Look up valid values with GET /v1/contract. - Omitted / null on POST /v1/task and validate-new-task — The project's main contract. - Omitted / null on create-sub-task — The parent task's contract. - 0 or negative — 400 (must be > 0 when present). - Not a contract of ProjectID — 500 Code 102 / 37042 (rest.projectmanagement.task-contract-not-on-project). Valid values come from GET /v1/contract.

Format: int32
HourlyRateIDinteger
Required

The contract hourly rate used for the task; 0 = the employee's default hourly rate. Refers to ContractHourlyRateID. - Null / omitted — Required (NotNull) — but an empty body fails earlier with 500 Code 100. - > 0 and not a rate of the contract — 500 Code 102 / 37944 or 37043 (rest.projectmanagement.task-hourly-rate-not-on-contract). - > 0, fixed-price contract on a project with hourly-rate model Calculated — Set to 0; the task's hourly rate is derived instead (TDR: TaskHourlyRate; other fixed price: the contract's target hourly rate). - TDR contract and HourlyRateID != 0 — TaskHourlyRate must then be 0 (400 'Hourly rate must be 0 when HourlyRateID is selected.'). > Not yet documented: values → lookup op.

Format: int32
BudgetHoursnumber
Required

Budgeted hours of the task. Unit: hours - Null / omitted — Required (NotNull, >= 0) — an empty body fails earlier with 500 Code 100. - Time & material contract, BudgetAmount and HourlyRateID also non-zero — 400: only two of BudgetHours, BudgetAmount, HourlyRateID may be non-zero. - HourlyRateID > 0 and BudgetHours = 0 — Derived: BudgetAmount / the rate's amount, rounded to InvoiceSetting_NumberOfDecimals. - TDR on a Calculated-rate project and BudgetHours = 0 — Derived: BudgetAmount / TaskHourlyRate (1 when the rate is 0).

Format: double
BudgetAmountnumber
Required

Budgeted revenue of the task. Unit: project currency - Null / omitted — Required (NotNull, >= 0) — an empty body fails earlier with 500 Code 100. - HourlyRateID > 0 and BudgetAmount = 0 — Derived: BudgetHours x the rate's amount. - TDR contract — Stored as the budget; the task's allocated revenue is PaymentAmount instead. - Otherwise — Also becomes the task's allocated revenue amount.

Format: double
TaskTypeIDintegernull

The task type (classification) of the task. Refers to TaskTypeRead.TaskTypeID. - 0 or negative — 400 (must be > 0 when present). - Unknown ID (create only) — 500 Code 102 / 37010 (rest.projectmanagement.task-type-not-found). validate-new-task does not check it. - Null — Stored as 0 (no task type). The account's 'task type required' setting is deliberately not enforced by the save rules. > Not yet documented: values → lookup op.

Format: int32
PaymentRecognitionModelinteger

How a task-driven-revenue (TDR) task recognises revenue. Conditional. Required (1 or 2) when the task's contract is TDR; ignored and reset to 0 otherwise. Allowed values: | Value | Name | Meaning | |---|---|---| | 0 | Undefined | Not a TDR task. Rejected (400) on a TDR contract. | | 1 | OverallPaymentPlan | Revenue follows the contract's overall payment plan; no instalment of its own. | | 2 | FixedPricePayment | The task has its own fixed-price instalment: PaymentAmount, PaymentProductNo, PaymentName and PaymentInvoiceDate become required and are written to it. |

Format: int32 • Options: 0, 1, 2
PaymentAmountnumber

TDR only — the task's allocated revenue, and with FixedPricePayment the amount of its instalment. Conditional. TDR contract: >= 0 (0 when omitted). Ignored otherwise. Can be set on create only. Unit: project currency - TDR contract — Becomes the task's allocated revenue amount (replaces BudgetAmount for that). - TDR + FixedPricePayment and the task has exactly one instalment after the save — Written as that instalment's Rate and Amount.

Format: double
TaskHourlyRatenumber

TDR only — the task's own hourly rate on a project whose hourly-rate model is Calculated. Conditional. TDR + FixedPricePayment: >= 0. Must be 0 when HourlyRateID != 0, and not all three of BudgetHours, BudgetAmount, TaskHourlyRate may be non-zero. Ignored on other contracts. Can be set on create only. Unit: project currency per hour - TDR, Calculated hourly-rate model, TaskHourlyRate = 0 — Derived: BudgetAmount / BudgetHours (1 when hours are 0). - TDR, Calculated hourly-rate model, TaskHourlyRate > 0 — Stored as the task's hourly rate; used to derive BudgetHours or BudgetAmount when one of them is 0.

Format: double
PaymentProductNostringnull

TDR fixed-price-payment only — product number of the task's instalment. Conditional. Required (non-empty) when the contract is TDR and PaymentRecognitionModel = 2; must exist in the project's legal entity whenever sent on a TDR contract. Can be set on create only. Refers to ProductNumber. - TDR contract, unknown number — 500 Code 102 / 37939 (rest.projectmanagement.task-payment-product-number-not-found). > Not yet documented: values → lookup op.

PaymentNamestringnull

TDR fixed-price-payment only — name (invoice text) of the task's instalment. Conditional. Required (non-empty) when the contract is TDR and PaymentRecognitionModel = 2. Ignored otherwise. Can be set on create only.

PaymentInvoiceDatestringnull

TDR fixed-price-payment only — invoice date of the task's instalment. Conditional. Required when the contract is TDR and PaymentRecognitionModel = 2. Ignored otherwise. Can be set on create only. Time zone: not yet documented. - Feature LockPaymentDateToFPTTaskDate on — On later task saves the instalment's invoice date is re-synced to the task's EndDate. > Not yet documented: constraints → timezone.

Format: date-time
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
ProjectIDinteger
Required

The project the task is created on.

Can be set on create only.

Refers to ProjectRead.ProjectID. Look up valid values with GET /v1/project/get-all.

  • 0 or omitted — Should be 400 'Project ID must be greater than 0', but the validator's contract rules crash first: 500 Code 100.

  • Unknown ID — 500 Code 102 / 37014 (rest.projectmanagement.project-not-found) — or 500 Code 100 when the validator's contract lookup runs first.

Valid values come from GET /v1/project/get-all.

ParentTaskIDinteger,null

The existing task the new task is placed under (create-sub-task only).

Can be set on create only.

Refers to TaskRead.TaskID. Look up valid values with GET /v1/task.

  • Sent as 0 or negative — 400 (must be > 0 when present).

  • create-sub-task: the task is on ANOTHER project — The parent is re-resolved by its WBS number inside ProjectID: the sub-task lands under the task of ProjectID that has the same WBS number, or the call fails with 500.

  • create-sub-task: null — Treated as task 0: 500 rest.projectmanagement.task-not-found (37001).

Valid values come from GET /v1/task.

TaskNamestring
Required

Display name of the task.

Not yet documented: constraints → max length.

TaskNostring,null

The task number shown next to the name (searchable by the time-tracking searches).

Copied as sent.

Not yet documented: notes.

Descriptionstring,null

Free-text description of the task.

StartDatestring
Required

Planned start of the task.

Time zone: not yet documented.

  • Omitted (0001-01-01) — 400 'StartDate is not a valid date.'

Not yet documented: constraints → timezone.

EndDatestring
Required

Planned end of the task.

Time zone: not yet documented.

  • Omitted (0001-01-01) — 400 with the message 'StartDate is not a valid date.'.

  • Before StartDate — 400 'EndDate must be equal to or greater than StartDate.'

  • Time-and-material basic contract — Becomes the invoice date of the task's instalment.

Not yet documented: constraints → timezone.

AdditionalTextIsRequiredboolean

When true, time registrations on this task must carry an additional comment.

IsBillableboolean

Default billable flag of time registered on the task.

Omitted = false (non-billable task). Read back as TaskRead.IsDefaultBillable.

IsReadyForInvoicingboolean

Marks the task (and, for TDR fixed-price-payment / time-and-material-basic tasks, its instalment) ready for invoicing.

ProjectSubContractIDinteger,null

The contract of the project the task is invoiced on.

Refers to ContractRead.ContractID. Look up valid values with GET /v1/contract.

  • Omitted / null on POST /v1/task and validate-new-task — The project's main contract.

  • Omitted / null on create-sub-task — The parent task's contract.

  • 0 or negative — 400 (must be > 0 when present).

  • Not a contract of ProjectID — 500 Code 102 / 37042 (rest.projectmanagement.task-contract-not-on-project).

Valid values come from GET /v1/contract.

HourlyRateIDinteger
Required

The contract hourly rate used for the task; 0 = the employee's default hourly rate.

Refers to ContractHourlyRateID.

  • Null / omitted — Required (NotNull) — but an empty body fails earlier with 500 Code 100.

  • 0 and not a rate of the contract — 500 Code 102 / 37944 or 37043 (rest.projectmanagement.task-hourly-rate-not-on-contract).

  • 0, fixed-price contract on a project with hourly-rate model Calculated — Set to 0; the task's hourly rate is derived instead (TDR: TaskHourlyRate; other fixed price: the contract's target hourly rate).

  • TDR contract and HourlyRateID != 0 — TaskHourlyRate must then be 0 (400 'Hourly rate must be 0 when HourlyRateID is selected.').

Not yet documented: values → lookup op.

BudgetHoursnumber
Required

Budgeted hours of the task.

Unit: hours

  • Null / omitted — Required (NotNull, >= 0) — an empty body fails earlier with 500 Code 100.

  • Time & material contract, BudgetAmount and HourlyRateID also non-zero — 400: only two of BudgetHours, BudgetAmount, HourlyRateID may be non-zero.

  • HourlyRateID > 0 and BudgetHours = 0 — Derived: BudgetAmount / the rate's amount, rounded to InvoiceSetting_NumberOfDecimals.

  • TDR on a Calculated-rate project and BudgetHours = 0 — Derived: BudgetAmount / TaskHourlyRate (1 when the rate is 0).

BudgetAmountnumber
Required

Budgeted revenue of the task.

Unit: project currency

  • Null / omitted — Required (NotNull, >= 0) — an empty body fails earlier with 500 Code 100.

  • HourlyRateID > 0 and BudgetAmount = 0 — Derived: BudgetHours x the rate's amount.

  • TDR contract — Stored as the budget; the task's allocated revenue is PaymentAmount instead.

  • Otherwise — Also becomes the task's allocated revenue amount.

TaskTypeIDinteger,null

The task type (classification) of the task.

Refers to TaskTypeRead.TaskTypeID.

  • 0 or negative — 400 (must be > 0 when present).

  • Unknown ID (create only) — 500 Code 102 / 37010 (rest.projectmanagement.task-type-not-found). validate-new-task does not check it.

  • Null — Stored as 0 (no task type). The account's 'task type required' setting is deliberately not enforced by the save rules.

Not yet documented: values → lookup op.

PaymentRecognitionModelinteger

How a task-driven-revenue (TDR) task recognises revenue.

Conditional. Required (1 or 2) when the task's contract is TDR; ignored and reset to 0 otherwise.

Allowed values:

ValueNameMeaning
0UndefinedNot a TDR task. Rejected (400) on a TDR contract.
1OverallPaymentPlanRevenue follows the contract's overall payment plan; no instalment of its own.
2FixedPricePaymentThe task has its own fixed-price instalment: PaymentAmount, PaymentProductNo, PaymentName and PaymentInvoiceDate become required and are written to it.
Allowed values:012
PaymentAmountnumber

TDR only — the task's allocated revenue, and with FixedPricePayment the amount of its instalment.

Conditional. TDR contract: >= 0 (0 when omitted). Ignored otherwise.

Can be set on create only.

Unit: project currency

  • TDR contract — Becomes the task's allocated revenue amount (replaces BudgetAmount for that).

  • TDR + FixedPricePayment and the task has exactly one instalment after the save — Written as that instalment's Rate and Amount.

TaskHourlyRatenumber

TDR only — the task's own hourly rate on a project whose hourly-rate model is Calculated.

Conditional. TDR + FixedPricePayment: >= 0. Must be 0 when HourlyRateID != 0, and not all three of BudgetHours, BudgetAmount, TaskHourlyRate may be non-zero. Ignored on other contracts.

Can be set on create only.

Unit: project currency per hour

  • TDR, Calculated hourly-rate model, TaskHourlyRate = 0 — Derived: BudgetAmount / BudgetHours (1 when hours are 0).

  • TDR, Calculated hourly-rate model, TaskHourlyRate > 0 — Stored as the task's hourly rate; used to derive BudgetHours or BudgetAmount when one of them is 0.

PaymentProductNostring,null

TDR fixed-price-payment only — product number of the task's instalment.

Conditional. Required (non-empty) when the contract is TDR and PaymentRecognitionModel = 2; must exist in the project's legal entity whenever sent on a TDR contract.

Can be set on create only.

Refers to ProductNumber.

  • TDR contract, unknown number — 500 Code 102 / 37939 (rest.projectmanagement.task-payment-product-number-not-found).

Not yet documented: values → lookup op.

PaymentNamestring,null

TDR fixed-price-payment only — name (invoice text) of the task's instalment.

Conditional. Required (non-empty) when the contract is TDR and PaymentRecognitionModel = 2. Ignored otherwise.

Can be set on create only.

PaymentInvoiceDatestring,null

TDR fixed-price-payment only — invoice date of the task's instalment.

Conditional. Required when the contract is TDR and PaymentRecognitionModel = 2. Ignored otherwise.

Can be set on create only.

Time zone: not yet documented.

  • Feature LockPaymentDateToFPTTaskDate on — On later task saves the instalment's invoice date is re-synced to the task's EndDate.

Not yet documented: constraints → timezone.

Responses

Propertiesobject

A short task representation for time-tracking pickers: the task's IDs, name and number, its parent, its project, and three flags that change how a registration on it behaves (fixed price, default billable, additional text required). It is not the full task (no dates, budget, status or contract). The TAF self link points to GET /v1/task/{TaskID}; entities also carry TAF actions (add-registration, start-time-tracker and, depending on the operation, create-task / create-sub-task / validate-new-task) describing other POST operations.

Linksarray
Actionsobject[]