Create a time-and-material contract
Adds a TimeMaterialBasic contract (model 1) to an existing project and returns it.
Creates a time-and-material (standard agreement) contract: registered hours are invoiced as registered, on ProjectID, with the fields of ContractCreate that this type accepts (the others are ignored — see the overrides). Answers 200 with the new contract as ContractRead, which carries no budgets: read them in the TimeLog UI or trust what you sent, keeping in mind the server-side derivations on ContractCreate's fields. Also creates the contract's hourly rates and customers from the project, and possibly a first instalment (see side effects). Not idempotent and not atomic. No project privilege is checked.
Use it to:
- Add a separately invoiced time-and-material contract (e.g. a change request) to an existing project
Not for:
- A dry run:
POST /v1/contract/validate-time-material-basic-contract - Recurring contracts (periodic balancing, continuous service, FPVI) — no REST v1 create
Behaviour:
- Not idempotent.
- Not safe to retry blindly. Every call inserts a new contract; there is no external key or dedup. After a timeout or a 500, list the project contracts (newest first) before retrying.
- Side effect: Inserts the contract (model 1 TimeMaterialBasic, the sent status and owner) and writes a contract-history entry.
- Side effect: Budget link: the project's FIRST contract is budget-linked (the project's budget hours / work amount are set from it); any later contract is not, and adding it clears the budget link of every other contract of the project.
- Side effect: IsDefaultExpenses true clears the flag on the project's other contracts.
- Side effect: Creates the contract's hourly rates and contract customers from the project; notifies the project (may activate an inactive project when the contract is active).
- Side effect: First instalment: None: time-and-material basic contracts get no first instalment.
- Side effect: Re-saves the project after the contract.
- Changes are visible to the next read immediately.
Call first: GET /v1/project/get-all, GET /v1/user, GET /v1/ContractModel
Next: GET /v1/contract/{contractID}, GET /v1/contract
Not yet documented: behaviour → side effects; examples.
curl -X POST "https://app3.timelog.com/your-account/api/v1/contract/create-time-material-basic-contract" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_TOKEN" \
-d '{
"ProjectID": 123,
"ContractName": "John Doe",
"ContractStatus": 42,
"ContractOwnerUserID": 123,
"BudgetWorkAmount": 3.14,
"BudgetWorkHour": 3.14,
"HasCompletionNotification": true,
"CompletionNotificationPercentage": 3.14,
"IsMileageBillable": true,
"IsDefaultExpenses": true,
"ContractTypeID": 123,
"BudgetExpensesAmount": 3.14,
"BudgetTravelAmount": 3.14,
"HasBudgetOverrunNotification": "null",
"TargetHourlyRate": 3.14,
"PaymentPlanAmount": 3.14,
"RevenueExprAmount": 3.14,
"RevenueTravelAmount": 3.14,
"IsExpensesLinked": true,
"IsTravelLinked": true,
"IsFixedHourlyRate": true,
"HourlyRatePrice": 29.99,
"HourlyRateName": "John Doe"
}'
import requests
import json
url = "https://app3.timelog.com/your-account/api/v1/contract/create-time-material-basic-contract"
headers = {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
}
data = {
"ProjectID": 123,
"ContractName": "John Doe",
"ContractStatus": 42,
"ContractOwnerUserID": 123,
"BudgetWorkAmount": 3.14,
"BudgetWorkHour": 3.14,
"HasCompletionNotification": true,
"CompletionNotificationPercentage": 3.14,
"IsMileageBillable": true,
"IsDefaultExpenses": true,
"ContractTypeID": 123,
"BudgetExpensesAmount": 3.14,
"BudgetTravelAmount": 3.14,
"HasBudgetOverrunNotification": "null",
"TargetHourlyRate": 3.14,
"PaymentPlanAmount": 3.14,
"RevenueExprAmount": 3.14,
"RevenueTravelAmount": 3.14,
"IsExpensesLinked": true,
"IsTravelLinked": true,
"IsFixedHourlyRate": true,
"HourlyRatePrice": 29.99,
"HourlyRateName": "John Doe"
}
response = requests.post(url, headers=headers, json=data)
print(response.json())
const response = await fetch("https://app3.timelog.com/your-account/api/v1/contract/create-time-material-basic-contract", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_API_TOKEN"
},
body: JSON.stringify({
"ProjectID": 123,
"ContractName": "John Doe",
"ContractStatus": 42,
"ContractOwnerUserID": 123,
"BudgetWorkAmount": 3.14,
"BudgetWorkHour": 3.14,
"HasCompletionNotification": true,
"CompletionNotificationPercentage": 3.14,
"IsMileageBillable": true,
"IsDefaultExpenses": true,
"ContractTypeID": 123,
"BudgetExpensesAmount": 3.14,
"BudgetTravelAmount": 3.14,
"HasBudgetOverrunNotification": "null",
"TargetHourlyRate": 3.14,
"PaymentPlanAmount": 3.14,
"RevenueExprAmount": 3.14,
"RevenueTravelAmount": 3.14,
"IsExpensesLinked": true,
"IsTravelLinked": true,
"IsFixedHourlyRate": true,
"HourlyRatePrice": 29.99,
"HourlyRateName": "John Doe"
})
});
const data = await response.json();
console.log(data);
package main
import (
"fmt"
"net/http"
"bytes"
"encoding/json"
)
func main() {
data := []byte(`{
"ProjectID": 123,
"ContractName": "John Doe",
"ContractStatus": 42,
"ContractOwnerUserID": 123,
"BudgetWorkAmount": 3.14,
"BudgetWorkHour": 3.14,
"HasCompletionNotification": true,
"CompletionNotificationPercentage": 3.14,
"IsMileageBillable": true,
"IsDefaultExpenses": true,
"ContractTypeID": 123,
"BudgetExpensesAmount": 3.14,
"BudgetTravelAmount": 3.14,
"HasBudgetOverrunNotification": "null",
"TargetHourlyRate": 3.14,
"PaymentPlanAmount": 3.14,
"RevenueExprAmount": 3.14,
"RevenueTravelAmount": 3.14,
"IsExpensesLinked": true,
"IsTravelLinked": true,
"IsFixedHourlyRate": true,
"HourlyRatePrice": 29.99,
"HourlyRateName": "John Doe"
}`)
req, err := http.NewRequest("POST", "https://app3.timelog.com/your-account/api/v1/contract/create-time-material-basic-contract", bytes.NewBuffer(data))
if err != nil {
panic(err)
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer YOUR_API_TOKEN")
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()
fmt.Println("Response Status:", resp.Status)
}
require 'net/http'
require 'json'
uri = URI('https://app3.timelog.com/your-account/api/v1/contract/create-time-material-basic-contract')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['Content-Type'] = 'application/json'
request['Authorization'] = 'Bearer YOUR_API_TOKEN'
request.body = '{
"ProjectID": 123,
"ContractName": "John Doe",
"ContractStatus": 42,
"ContractOwnerUserID": 123,
"BudgetWorkAmount": 3.14,
"BudgetWorkHour": 3.14,
"HasCompletionNotification": true,
"CompletionNotificationPercentage": 3.14,
"IsMileageBillable": true,
"IsDefaultExpenses": true,
"ContractTypeID": 123,
"BudgetExpensesAmount": 3.14,
"BudgetTravelAmount": 3.14,
"HasBudgetOverrunNotification": "null",
"TargetHourlyRate": 3.14,
"PaymentPlanAmount": 3.14,
"RevenueExprAmount": 3.14,
"RevenueTravelAmount": 3.14,
"IsExpensesLinked": true,
"IsTravelLinked": true,
"IsFixedHourlyRate": true,
"HourlyRatePrice": 29.99,
"HourlyRateName": "John Doe"
}'
response = http.request(request)
puts response.body
{
"Properties": {
"ContractID": 123,
"ContractGuid": "123e4567-e89b-12d3-a456-426614174000",
"ContractModelType": 42,
"ProjectID": 123,
"IsMainContract": true,
"ContractName": "John Doe",
"ContractStatus": 42,
"IsMileageBillable": true,
"IsDefaultExpenses": "null",
"ContractTypeID": 123,
"ContractTypeName": "John Doe"
},
"Links": [
{
"Href": "example_string",
"Rel": "example_string"
}
],
"Actions": [
{}
]
}
{
"Code": 200,
"Details": [
"'Project ID' must be greater than '0'.",
"'Contract Name' must not be empty.",
"'Contract Status' has a range of values which does not include '0'."
],
"Message": "Invalid model state error.",
"Parameters": "contractModel: {...}",
"Url": "https://app{server-number}.timelog.com/{account}/api/v1/contract/create-time-material-basic-contract"
}
{
"error": "Unauthorized",
"message": "Authentication required. Please provide a valid API token",
"code": 401
}
{
"error": "Internal Server Error",
"message": "An unexpected error occurred on the server",
"code": 500,
"requestId": "req_1234567890"
}
/v1/contract/create-time-material-basic-contract
Target server for requests. Edit to use your own host.
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.
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.The media type of the request body
The project to add the contract to. Must be > 0 (400) and exist (37014, 500).
Can be set on create only.
Refers to ProjectRead.ProjectID. Look up valid values with GET /v1/project/get-all.
Valid values come from GET /v1/project/get-all.
Display name of the new contract. Kept as sent (the server generates a name only when it is empty, which the validator already forbids). Can be set on create only. > Not yet documented: constraints → max length.
Initial status of the contract. 0 or an undefined value is rejected (400 "'Contract Status' has a range of values which does not include '0'.").
Can be set on create only.
- All five types — Set on the new contract through ProjectSubContract.ChangeStatus before the first save.
Allowed values:
| Value | Name | Meaning |
|---|---|---|
| 1 | Quotation | Create the contract in quote stage (not yet running). |
| 2 | Active | Create a running contract. |
| 3 | Completed | Create the contract already closed as finished. |
| 4 | Cancelled | Create the contract already closed as cancelled. |
> Not yet documented: values → members.
USER ID (not employee ID) of the contract owner. Must be an existing (37040) and active (37931) user. In practice required: the validator accepts 0 and the save logic would default 0 to the project manager, but the controller validates the owner before that and rejects 0 with 37040.
Can be set on create only.
Refers to UserRead.UserID. Look up valid values with GET /v1/user.
Valid values come from GET /v1/user.
> Not yet documented: behaviour.
Budgeted revenue for work (hours × rate) on the contract, in project currency. Its handling differs by type — see behaviour. Can be set on create only. Unit: project currency - TMB, TMAEB — Stored as sent. TMAEB: also part of the first instalment (BudgetWorkAmount + BudgetExpensesAmount + BudgetTravelAmount). - FPB, TDR — together with a non-zero TargetHourlyRate — 400 "BudgetWorkAmount must be 0 when TargetHourlyRate is added." (and the mirror message on TargetHourlyRate). - FPB, TDR — BudgetWorkHour > 0 — Stored as BudgetWorkHour × (BudgetWorkAmount / BudgetWorkHour), rounded — equal to the sent value up to rounding; TargetHourlyRate is derived from it. - FPB, TDR — BudgetWorkHour = 0 — Stored as 0: the derived target rate is 0 when there are no hours, so the amount is lost. - PS — IsFixedHourlyRate false — Stored as sent; it is also the amount of the first instalment. - PS — IsFixedHourlyRate true, together with a non-zero BudgetWorkHour — 400 "BudgetWorkAmount must be 0 when BudgetWorkHour is added." - PS — IsFixedHourlyRate true, 0 and BudgetWorkHour > 0 — Derived as BudgetWorkHour × HourlyRatePrice on the second save. The first instalment is created from the SENT value (0 → no instalment). - More decimals than InvoiceSetting_NumberOfDecimals — 400; the message names AmountIncludingVatExpenseCurrency instead of this field.
Budgeted work hours on the contract. Can be set on create only. Unit: hours - TMB, TMAEB, FPB, TDR — Stored as sent. FPB / TDR: it is the divisor of the target-rate derivation — send it whenever you send BudgetWorkAmount or TargetHourlyRate. - PS — IsFixedHourlyRate false — applied - PS — IsFixedHourlyRate true, together with a non-zero BudgetWorkAmount — 400 "BudgetWorkHour must be 0 when BudgetWorkAmount is added." - PS — IsFixedHourlyRate true, 0 and BudgetWorkAmount > 0 — Derived as BudgetWorkAmount / HourlyRatePrice. With HourlyRatePrice 0 this divides by zero.
Turn on the contract's completion notification, which fires at CompletionNotificationPercentage. Can be set on create only. - All five types — applied > Not yet documented: description.
Threshold in percent for the completion notification. Can be set on create only. Unit: percent - All five types — applied - Outside 0–100 — 400 (InclusiveBetween).
Default billable flag for mileage registered on this contract. Can be set on create only. - All five types — applied
Make this the project's default contract for expenses. Can be set on create only. - true (all five types) — Clears IsDefaultExpenses on every other contract of the project (at most one default per project).
Account-defined contract type (a classification independent of the contract model). 0 = none. When > 0 it must exist (37958). When the account feature ContractTypeIsRequired is on, a value >= 1 is required (37957).
Conditional. Required (>= 1) when the account feature ContractTypeIsRequired is active; otherwise optional (0 = none).
Can be set on create only.
Refers to ContractTypeRead.ContractTypeID.
- Feature ContractTypeIsRequired on and value < 1 — 37957, 500 (controller, before the contract is built).
- Value > 0 that is not a contract type — 37958, 500 (save business rules, before the insert).
- 37958 is still checked.
> Not yet documented: values → lookup op.
Budgeted expenses on the contract, in project currency. Can be set on create only. Unit: project currency - TMB, TMAEB — TMAEB: part of the first instalment. - FPB, TDR — When IsExpensesLinked is true it is ALSO written as RevenueExprAmount. - PS — Not part of the prepaid body.
Budgeted travel (mileage / travel expenses) on the contract, in project currency. Can be set on create only. Unit: project currency - TMB, TMAEB — TMAEB: part of the first instalment. - FPB, TDR — When IsTravelLinked is true it is ALSO written as RevenueTravelAmount. - PS — Not part of the prepaid body.
Turn on the budget-overrun notification of a time-and-material contract. Can be set on create only. Null: null = false. - TMB, TMAEB — null is stored as false. - FPB, PS, TDR — Not part of those bodies. > Not yet documented: description.
Fixed price contracts: the hourly rate the fixed price is expected to yield, in project currency per hour. Alternative to BudgetWorkAmount — send one of them, together with BudgetWorkHour. Can be set on create only. Unit: project currency per hour - FPB, TDR — together with a non-zero BudgetWorkAmount — 400 "TargetHourlyRate must be 0 when BudgetWorkAmount is added." - FPB, TDR — BudgetWorkHour > 0 — Kept (rounded); BudgetWorkAmount becomes BudgetWorkHour × TargetHourlyRate. When 0 it is derived as BudgetWorkAmount / BudgetWorkHour. - FPB, TDR — BudgetWorkHour = 0 — Stored as 0. - FPB (not TDR) — After the save, every task on this contract whose hourly-rate model is not Allocated gets this rate (none exist yet on a new contract). - TMB, TMAEB, PS — Not part of those bodies.
The contract's fixed price, in project currency. When not 0, the create also adds a first instalment of this amount to the billing plan, dated today. Can be set on create only. Unit: project currency - FPB, TDR — Stored; != 0 → one instalment of PaymentPlanAmount named by the default payment name, invoice date = server 'now' (not on multi-customer projects). - TMB, TMAEB, PS — Not part of those bodies.
Fixed price contracts: expected revenue from expenses, in project currency. Can be set on create only. Unit: project currency - FPB, TDR — IsExpensesLinked false — applied - FPB, TDR — IsExpensesLinked true — Replaced by BudgetExpensesAmount. - TMB, TMAEB, PS — Not part of those bodies. > Not yet documented: description.
Fixed price contracts: expected revenue from travel, in project currency. Can be set on create only. Unit: project currency - FPB, TDR — IsTravelLinked false — applied - FPB, TDR — IsTravelLinked true — Replaced by BudgetTravelAmount. - TMB, TMAEB, PS — Not part of those bodies.
Fixed price contracts: when true, expense revenue (RevenueExprAmount) follows the expense budget (BudgetExpensesAmount). Can be set on create only. - FPB, TDR — applied - TMB, TMAEB — Not part of those bodies; the adapter forces false. - PS — Not part of the prepaid body.
Fixed price contracts: when true, travel revenue (RevenueTravelAmount) follows the travel budget (BudgetTravelAmount). Can be set on create only. - FPB, TDR — applied - TMB, TMAEB — Not part of those bodies; the adapter forces false. - PS — Not part of the prepaid body.
Prepaid contracts: when true, the budget is kept consistent with HourlyRatePrice — send EITHER BudgetWorkHour OR BudgetWorkAmount (400 if both) and the other is derived. When false, both are stored as sent. Can be set on create only. - PS — Set through ChangeIsFixedHourlyRate; drives the derivation in UpdatePrepaidContractCreatedFromApi. - TMB, FPB, TMAEB, TDR — Not part of those bodies. > Not yet documented: description.
Prepaid contracts: price of the project-specific contract hourly rate that the create adds to the new contract, in the project's price-list currency. Can be set on create only. Unit: project currency per hour - PS — After the first save a contract hourly rate (HourlyRateName, this price, project CurrencyListID) is created and set as the contract's hourly rate. - Negative — 400 (GreaterThanOrEqualTo 0). - TMB, FPB, TMAEB, TDR — Not part of those bodies.
Prepaid contracts: name of the contract hourly rate created with HourlyRatePrice. Can be set on create only. - PS — applied - TMB, FPB, TMAEB, TDR — Not part of those bodies.
Request Preview
Response
Response will appear here after sending the request
Authentication
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
The project to add the contract to. Must be > 0 (400) and exist (37014, 500).
Can be set on create only.
Refers to ProjectRead.ProjectID. Look up valid values with GET /v1/project/get-all.
Valid values come from GET /v1/project/get-all.
Display name of the new contract. Kept as sent (the server generates a name only when it is empty, which the validator already forbids).
Can be set on create only.
Not yet documented: constraints → max length.
Initial status of the contract. 0 or an undefined value is rejected (400 "'Contract Status' has a range of values which does not include '0'.").
Can be set on create only.
- All five types — Set on the new contract through ProjectSubContract.ChangeStatus before the first save.
Allowed values:
| Value | Name | Meaning |
|---|---|---|
1 | Quotation | Create the contract in quote stage (not yet running). |
2 | Active | Create a running contract. |
3 | Completed | Create the contract already closed as finished. |
4 | Cancelled | Create the contract already closed as cancelled. |
Not yet documented: values → members.
1234USER ID (not employee ID) of the contract owner. Must be an existing (37040) and active (37931) user. In practice required: the validator accepts 0 and the save logic would default 0 to the project manager, but the controller validates the owner before that and rejects 0 with 37040.
Can be set on create only.
Refers to UserRead.UserID. Look up valid values with GET /v1/user.
Valid values come from GET /v1/user.
Not yet documented: behaviour.
Budgeted revenue for work (hours × rate) on the contract, in project currency. Its handling differs by type — see behaviour.
Can be set on create only.
Unit: project currency
-
TMB, TMAEB — Stored as sent. TMAEB: also part of the first instalment (BudgetWorkAmount + BudgetExpensesAmount + BudgetTravelAmount).
-
FPB, TDR — together with a non-zero TargetHourlyRate — 400 "BudgetWorkAmount must be 0 when TargetHourlyRate is added." (and the mirror message on TargetHourlyRate).
-
FPB, TDR — BudgetWorkHour > 0 — Stored as BudgetWorkHour × (BudgetWorkAmount / BudgetWorkHour), rounded — equal to the sent value up to rounding; TargetHourlyRate is derived from it.
-
FPB, TDR — BudgetWorkHour = 0 — Stored as 0: the derived target rate is 0 when there are no hours, so the amount is lost.
-
PS — IsFixedHourlyRate false — Stored as sent; it is also the amount of the first instalment.
-
PS — IsFixedHourlyRate true, together with a non-zero BudgetWorkHour — 400 "BudgetWorkAmount must be 0 when BudgetWorkHour is added."
-
PS — IsFixedHourlyRate true, 0 and BudgetWorkHour > 0 — Derived as BudgetWorkHour × HourlyRatePrice on the second save. The first instalment is created from the SENT value (0 → no instalment).
-
More decimals than InvoiceSetting_NumberOfDecimals — 400; the message names AmountIncludingVatExpenseCurrency instead of this field.
Budgeted work hours on the contract.
Can be set on create only.
Unit: hours
-
TMB, TMAEB, FPB, TDR — Stored as sent. FPB / TDR: it is the divisor of the target-rate derivation — send it whenever you send BudgetWorkAmount or TargetHourlyRate.
-
PS — IsFixedHourlyRate false — applied
-
PS — IsFixedHourlyRate true, together with a non-zero BudgetWorkAmount — 400 "BudgetWorkHour must be 0 when BudgetWorkAmount is added."
-
PS — IsFixedHourlyRate true, 0 and BudgetWorkAmount > 0 — Derived as BudgetWorkAmount / HourlyRatePrice. With HourlyRatePrice 0 this divides by zero.
Turn on the contract's completion notification, which fires at CompletionNotificationPercentage.
Can be set on create only.
- All five types — applied
Not yet documented: description.
Threshold in percent for the completion notification.
Can be set on create only.
Unit: percent
-
All five types — applied
-
Outside 0–100 — 400 (InclusiveBetween).
Default billable flag for mileage registered on this contract.
Can be set on create only.
- All five types — applied
Make this the project's default contract for expenses.
Can be set on create only.
- true (all five types) — Clears IsDefaultExpenses on every other contract of the project (at most one default per project).
Account-defined contract type (a classification independent of the contract model). 0 = none. When > 0 it must exist (37958). When the account feature ContractTypeIsRequired is on, a value >= 1 is required (37957).
Conditional. Required (>= 1) when the account feature ContractTypeIsRequired is active; otherwise optional (0 = none).
Can be set on create only.
Refers to ContractTypeRead.ContractTypeID.
-
Feature ContractTypeIsRequired on and value < 1 — 37957, 500 (controller, before the contract is built).
-
Value > 0 that is not a contract type — 37958, 500 (save business rules, before the insert).
-
37958 is still checked.
Not yet documented: values → lookup op.
Budgeted expenses on the contract, in project currency.
Can be set on create only.
Unit: project currency
-
TMB, TMAEB — TMAEB: part of the first instalment.
-
FPB, TDR — When IsExpensesLinked is true it is ALSO written as RevenueExprAmount.
-
PS — Not part of the prepaid body.
Budgeted travel (mileage / travel expenses) on the contract, in project currency.
Can be set on create only.
Unit: project currency
-
TMB, TMAEB — TMAEB: part of the first instalment.
-
FPB, TDR — When IsTravelLinked is true it is ALSO written as RevenueTravelAmount.
-
PS — Not part of the prepaid body.
Turn on the budget-overrun notification of a time-and-material contract.
Can be set on create only.
Null: null = false.
-
TMB, TMAEB — null is stored as false.
-
FPB, PS, TDR — Not part of those bodies.
Not yet documented: description.
Fixed price contracts: the hourly rate the fixed price is expected to yield, in project currency per hour. Alternative to BudgetWorkAmount — send one of them, together with BudgetWorkHour.
Can be set on create only.
Unit: project currency per hour
-
FPB, TDR — together with a non-zero BudgetWorkAmount — 400 "TargetHourlyRate must be 0 when BudgetWorkAmount is added."
-
FPB, TDR — BudgetWorkHour > 0 — Kept (rounded); BudgetWorkAmount becomes BudgetWorkHour × TargetHourlyRate. When 0 it is derived as BudgetWorkAmount / BudgetWorkHour.
-
FPB, TDR — BudgetWorkHour = 0 — Stored as 0.
-
FPB (not TDR) — After the save, every task on this contract whose hourly-rate model is not Allocated gets this rate (none exist yet on a new contract).
-
TMB, TMAEB, PS — Not part of those bodies.
The contract's fixed price, in project currency. When not 0, the create also adds a first instalment of this amount to the billing plan, dated today.
Can be set on create only.
Unit: project currency
-
FPB, TDR — Stored; != 0 → one instalment of PaymentPlanAmount named by the default payment name, invoice date = server 'now' (not on multi-customer projects).
-
TMB, TMAEB, PS — Not part of those bodies.
Fixed price contracts: expected revenue from expenses, in project currency.
Can be set on create only.
Unit: project currency
-
FPB, TDR — IsExpensesLinked false — applied
-
FPB, TDR — IsExpensesLinked true — Replaced by BudgetExpensesAmount.
-
TMB, TMAEB, PS — Not part of those bodies.
Not yet documented: description.
Fixed price contracts: expected revenue from travel, in project currency.
Can be set on create only.
Unit: project currency
-
FPB, TDR — IsTravelLinked false — applied
-
FPB, TDR — IsTravelLinked true — Replaced by BudgetTravelAmount.
-
TMB, TMAEB, PS — Not part of those bodies.
Fixed price contracts: when true, expense revenue (RevenueExprAmount) follows the expense budget (BudgetExpensesAmount).
Can be set on create only.
-
FPB, TDR — applied
-
TMB, TMAEB — Not part of those bodies; the adapter forces false.
-
PS — Not part of the prepaid body.
Fixed price contracts: when true, travel revenue (RevenueTravelAmount) follows the travel budget (BudgetTravelAmount).
Can be set on create only.
-
FPB, TDR — applied
-
TMB, TMAEB — Not part of those bodies; the adapter forces false.
-
PS — Not part of the prepaid body.
Prepaid contracts: when true, the budget is kept consistent with HourlyRatePrice — send EITHER BudgetWorkHour OR BudgetWorkAmount (400 if both) and the other is derived. When false, both are stored as sent.
Can be set on create only.
-
PS — Set through ChangeIsFixedHourlyRate; drives the derivation in UpdatePrepaidContractCreatedFromApi.
-
TMB, FPB, TMAEB, TDR — Not part of those bodies.
Not yet documented: description.
Prepaid contracts: price of the project-specific contract hourly rate that the create adds to the new contract, in the project's price-list currency.
Can be set on create only.
Unit: project currency per hour
-
PS — After the first save a contract hourly rate (HourlyRateName, this price, project CurrencyListID) is created and set as the contract's hourly rate.
-
Negative — 400 (GreaterThanOrEqualTo 0).
-
TMB, FPB, TMAEB, TDR — Not part of those bodies.
Prepaid contracts: name of the contract hourly rate created with HourlyRatePrice.
Can be set on create only.
-
PS — applied
-
TMB, FPB, TMAEB, TDR — Not part of those bodies.
Responses
A contract of a project: HOW the work on the project is invoiced. A project has one or more contracts; each has a contract model (time and material, fixed price, prepaid, ...), a status and an optional account-defined contract type. Tasks, payments (instalments), expenses and mileage are booked on a contract. The TAF self link points to GET /v1/contract/{ContractID}; each entity also lists the ten contract TAF actions (five creates, five validates).