ProjectsUpdate a project

Update a project

Updates a project's header fields (name, customer, people, type, dates, budgets).

MIXED replace / patch semantics: Name, CustomerID, ContactID, Description and ProjectManagerID are always written; the nullable fields are written only when sent. Answers 200 with the body null; read the project back with GET. Status is changed with PUT /v1/project/{projectID}/status.

Use it to:

  • Sync name, project manager or budget changes from a CRM / PSA

Not for:

  • Status changes → PUT /v1/project/{projectID}/status

Rules across fields:

  • R1: Effective end date (sent, else stored) must be on or after the effective start date (sent, else stored); checked only when at least one date is sent.

Behaviour:

  • Idempotent.
  • Safe to retry only under a condition. Repeating the same body gives the same state, but omitted Description / ContactID are cleared each time.
  • Side effect: Writes the project row (last-modified fields set), saves invoice settings, adds the project manager to the resource group, and notifies contract customers, task search and sales-share read models.
  • Side effect: When project dates are locked to the task plan, Save recalculates the project dates from the task plan.
  • Changes are visible to the next read immediately.

Call first: GET /v1/project/{projectID}

Next: GET /v1/project/{projectID}

See also: PUT /v1/project/{projectID}/status

curl -X PUT "https://app3.timelog.com/your-account/api/v1/project/123" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
  "Name": "John Doe",
  "ProjectNo": "example_string",
  "CustomerID": 123,
  "ContactID": 123,
  "Description": "null",
  "DepartmentID": "null",
  "ProjectManagerID": 123,
  "AccountManagerID": "null",
  "PartnerID": "null",
  "ProjectTypeID": "null",
  "ProjectCategoryID": "null",
  "ProjectStartDate": "null",
  "ProjectEndDate": "null",
  "BudgetWorkHours": "null",
  "BudgetWorkAmount": "null",
  "LanguageID": "null"
}'
"null"
PUT
/v1/project/{projectID}
PUT
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.

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.
path
projectIDinteger
Required

The project to update.

Format: int32
Content-Typestring
Required

The media type of the request body

Options: application/json
Namestring
Required

Project name. Always written.

ProjectNostring

Project number. Written only when non-empty AND the project-number auto-number series is off; otherwise ignored. - Empty / omitted — Number unchanged. - Project-number auto-number is active — Number unchanged, no error.

CustomerIDinteger
Required

The project's customer. Always written; changing it runs ProjectCanChangeCustomer. Refers to CustomerRead.CustomerID. Look up valid values with GET /v1/customer. Valid values come from GET /v1/customer.

Format: int32
ContactIDinteger

Customer contact. Always written: omitted = 0 = the contact is removed. Refers to ContactRead.ContactID. Default: 0 (clears the contact) - Omitted — 0 is written — the stored contact is cleared.

Format: int32
Descriptionstringnull

Project description. Always written: omitted = null = the description is cleared. - Omitted or null — null is written — the stored description is cleared.

DepartmentIDintegernull

Handling department. Written only when sent and the Departments feature is on. Refers to DepartmentRead.DepartmentID. Look up valid values with GET /v1/department. - Feature Departments is off — ignored Valid values come from GET /v1/department.

Format: int32
ProjectManagerIDinteger
Required

Project manager, as a USER ID (existing, active). Always written. Refers to UserRead.UserID. Look up valid values with GET /v1/user. Valid values come from GET /v1/user.

Format: int32
AccountManagerIDintegernull

Account manager, as a USER ID. Written only when sent and the AccountManager feature is on. Cannot be cleared (null = keep). Refers to UserRead.UserID. Look up valid values with GET /v1/user. - Feature AccountManager is off — ignored Valid values come from GET /v1/user.

Format: int32
PartnerIDintegernull

Partner, as a USER ID. Written only when sent and the Partner feature is on. Refers to UserRead.UserID. Look up valid values with GET /v1/user. - Feature Partner is off — ignored Valid values come from GET /v1/user.

Format: int32
ProjectTypeIDintegernull

Project type. Written only when sent and the ProjectType feature is on. Refers to ProjectTypeRead.ProjectTypeID. - Feature ProjectType is off — ignored

Format: int32
ProjectCategoryIDintegernull

Project category. Written only when sent and the ProjectCategory feature is on. Refers to ProjectCategoryRead.ProjectCategoryID. - Feature ProjectCategory is off — ignored

Format: int32
ProjectStartDatestringnull

New start date (date part compared). Rejected (400) unless the ProjectSchedule feature is on and LockProjectDateWithTaskPlan is off. - ProjectSchedule feature off — 400 "ProjectStartDate cannot be updated because the Project schedule feature is not active on this site." - LockProjectDateWithTaskPlan feature on — 400 "…project dates are locked to the task plan on this site."

Format: date-time
ProjectEndDatestringnull

New end date (stored as ContractEndDate). Same feature gates as ProjectStartDate. Must be on or after the effective start date. - End before start (both sent) — 400 validation "ProjectEndDate must be on or after ProjectStartDate." - Only one date sent and it crosses the stored other date — 400 Code 400, same message.

Format: date-time
BudgetWorkHoursnumbernull

Budgeted work hours; null = keep. Unit: hours

Format: double
BudgetWorkAmountnumbernull

Budgeted work amount; null = keep. Unit: project currency

Format: double
LanguageIDintegernull

Invoice language; written only when sent and InvoiceMultilingual is on. - Any other value — Validation (400). - Feature InvoiceMultilingual is off — ignored Allowed values: | Value | Name | Meaning | |---|---|---| | 1 | Danish | Invoices in Danish. | | 2 | English | Invoices in English. | | 4 | Swedish | Invoices in Swedish. | | 15 | Norwegian | Invoices in Norwegian. | | 16 | German | Invoices in German. | | 17 | Dutch | Invoices in Dutch. | | 18 | French | Invoices in French. |

Format: int32 • Options: 1, 2, 4, 15, 16, 17, 18
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.

Path Parameters

projectIDinteger
Required

The project to update.

Body

application/json
Namestring
Required

Project name. Always written.

ProjectNostring

Project number. Written only when non-empty AND the project-number auto-number series is off; otherwise ignored.

  • Empty / omitted — Number unchanged.

  • Project-number auto-number is active — Number unchanged, no error.

CustomerIDinteger
Required

The project's customer. Always written; changing it runs ProjectCanChangeCustomer.

Refers to CustomerRead.CustomerID. Look up valid values with GET /v1/customer.

Valid values come from GET /v1/customer.

ContactIDinteger

Customer contact. Always written: omitted = 0 = the contact is removed.

Refers to ContactRead.ContactID.

Default: 0 (clears the contact)

  • Omitted — 0 is written — the stored contact is cleared.
Descriptionstring,null

Project description. Always written: omitted = null = the description is cleared.

  • Omitted or null — null is written — the stored description is cleared.
DepartmentIDinteger,null

Handling department. Written only when sent and the Departments feature is on.

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

  • Feature Departments is off — ignored

Valid values come from GET /v1/department.

ProjectManagerIDinteger
Required

Project manager, as a USER ID (existing, active). Always written.

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

Valid values come from GET /v1/user.

AccountManagerIDinteger,null

Account manager, as a USER ID. Written only when sent and the AccountManager feature is on. Cannot be cleared (null = keep).

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

  • Feature AccountManager is off — ignored

Valid values come from GET /v1/user.

PartnerIDinteger,null

Partner, as a USER ID. Written only when sent and the Partner feature is on.

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

  • Feature Partner is off — ignored

Valid values come from GET /v1/user.

ProjectTypeIDinteger,null

Project type. Written only when sent and the ProjectType feature is on.

Refers to ProjectTypeRead.ProjectTypeID.

  • Feature ProjectType is off — ignored
ProjectCategoryIDinteger,null

Project category. Written only when sent and the ProjectCategory feature is on.

Refers to ProjectCategoryRead.ProjectCategoryID.

  • Feature ProjectCategory is off — ignored
ProjectStartDatestring,null

New start date (date part compared). Rejected (400) unless the ProjectSchedule feature is on and LockProjectDateWithTaskPlan is off.

  • ProjectSchedule feature off — 400 "ProjectStartDate cannot be updated because the Project schedule feature is not active on this site."

  • LockProjectDateWithTaskPlan feature on — 400 "…project dates are locked to the task plan on this site."

ProjectEndDatestring,null

New end date (stored as ContractEndDate). Same feature gates as ProjectStartDate. Must be on or after the effective start date.

  • End before start (both sent) — 400 validation "ProjectEndDate must be on or after ProjectStartDate."

  • Only one date sent and it crosses the stored other date — 400 Code 400, same message.

BudgetWorkHoursnumber,null

Budgeted work hours; null = keep.

Unit: hours

BudgetWorkAmountnumber,null

Budgeted work amount; null = keep.

Unit: project currency

LanguageIDinteger,null

Invoice language; written only when sent and InvoiceMultilingual is on.

  • Any other value — Validation (400).

  • Feature InvoiceMultilingual is off — ignored

Allowed values:

ValueNameMeaning
1DanishInvoices in Danish.
2EnglishInvoices in English.
4SwedishInvoices in Swedish.
15NorwegianInvoices in Norwegian.
16GermanInvoices in German.
17DutchInvoices in Dutch.
18FrenchInvoices in French.
Allowed values:12415161718

Responses

Success without content: HTTP 200 with the literal JSON body null. Literal JSON null.