ProjectsUpdate the payment-plan amount of a recurring contract

Update the payment-plan amount of a recurring contract

Sets a new payment-plan amount on a continuous-service or continuous item-invoicing contract and returns the contract.

Changes the per-period fixed price (PaymentPlanAmount) of an existing recurring contract and derives its monthly work budget (BudgetWorkAmount = round(amount / RecurrenceMonth, 2)). Only models 7 (ContinuousService) and 8 (ContinuousItemInvoicing) are changed. Saving the contract regenerates its recurring instalments in the billing plan. A non-recurring contract is left unchanged and still answers 200; model 4 answers 500. Answers 200 with the contract as ContractRead (which shows neither amount — keep what you sent). There is no body validation: every bad input is a 500. No project privilege is checked.

Use it to:

  • Index or renegotiate the periodic fee of a continuous-service (subscription-like) contract from a billing or CRM system

Not for:

  • A dry run: POST /v1/contract/validate-update-recurring-contract-payment-plan-amount (same body, writes nothing)
  • Non-recurring contracts (models 1, 2, 3, 5, 6): the call is a silent no-op

Rules across fields:

  • R1: ProjectSubContractId should be a contract of ProjectId. Not enforced: any existing project is accepted and used as the save context.

Behaviour:

  • Idempotent.
  • The same amount sent twice leaves the same contract state; each call still re-saves the contract and regenerates its recurring instalments.
  • Safe to retry only under a condition. Safe to repeat with the same amount. After a 500 the amount may already be stored while the instalments were not regenerated: retry with the same amount.
  • Side effect: Models 7 / 8: stores PaymentPlanAmount and the derived BudgetWorkAmount.
  • Side effect: Writes a contract-history entry (NotifyProjectSubContractUpdated) and notifies invoicing potential.
  • Side effect: Saves the contract's recurrence and regenerates its recurring instalments in the billing plan (GeneratePaymentsForRecurrenceAdvanceContract with overwriteExistingData = true).
  • Side effect: Recalculates the contract's estimated values (PaymentPlanAmount / BudgetWorkAmount changed).
  • Side effect: Other models: nothing is written.
  • On failure: Not atomic: the contract row is updated before the contract-customer save and the recurrence save; a failure there answers 500 and the new amount stays (only new contracts are deleted on failure).
  • Changes are visible to the next read immediately.

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

Next: GET /v1/payment

See also: POST /v1/contract/validate-update-recurring-contract-payment-plan-amount

Not yet documented: behaviour → side effects; errors; examples.

curl -X POST "https://app3.timelog.com/your-account/api/v1/contract/update-recurring-contract-payment-plan-amount" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
  "ProjectId": 123,
  "ProjectSubContractId": 123,
  "PaymentPlanAmount": 3.14
}'
{
  "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": [
    {}
  ]
}
POST
/v1/contract/update-recurring-contract-payment-plan-amount
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 contract belongs to. Used only as the save context (budget sync, multi-customer handling, recalculation); it is NOT checked against the contract's own project. An unknown or 0 value fails with a 500 (captured for 0). Refers to ProjectRead.ProjectID. Look up valid values with GET /v1/project/get-all. - 0 / omitted / unknown — 500 Code 100, no 400. - An existing project that is not the contract's project — Accepted; the save runs with that project as context. Valid values come from GET /v1/project/get-all.

Format: int32
ProjectSubContractIdinteger
Required

The contract to update (ContractID in ContractRead). Unknown or 0 fails with a 500. Refers to ContractRead.ContractID. Look up valid values with GET /v1/contract. - 0 / omitted / unknown — 500 Code 100. - A contract that is not model 4, 7 or 8 (not recurring) — Nothing changes; 200. Valid values come from GET /v1/contract.

Format: int32
PaymentPlanAmountnumber
Required

The contract's new payment-plan amount (the fixed price per recurrence period), in the project currency. The server also sets the contract's BudgetWorkAmount = round(PaymentPlanAmount / RecurrenceMonth, 2, away from zero) — the per-month work budget. No range, sign or decimal check. Unit: project currency, per recurrence period - Model 7 or 8 — PaymentPlanAmount stored; BudgetWorkAmount derived. - Model 7 (continuous service) — 37633 when round(amount / months, 2) differs from the contract's allocated budget amount — 'You must allocate all revenue amount to proceed.' - Omitted — 0 is applied (non-nullable). > Not yet documented: constraints → unit.

Format: double
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 contract belongs to. Used only as the save context (budget sync, multi-customer handling, recalculation); it is NOT checked against the contract's own project. An unknown or 0 value fails with a 500 (captured for 0).

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

  • 0 / omitted / unknown — 500 Code 100, no 400.

  • An existing project that is not the contract's project — Accepted; the save runs with that project as context.

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

ProjectSubContractIdinteger
Required

The contract to update (ContractID in ContractRead). Unknown or 0 fails with a 500.

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

  • 0 / omitted / unknown — 500 Code 100.

  • A contract that is not model 4, 7 or 8 (not recurring) — Nothing changes; 200.

Valid values come from GET /v1/contract.

PaymentPlanAmountnumber
Required

The contract's new payment-plan amount (the fixed price per recurrence period), in the project currency. The server also sets the contract's BudgetWorkAmount = round(PaymentPlanAmount / RecurrenceMonth, 2, away from zero) — the per-month work budget. No range, sign or decimal check.

Unit: project currency, per recurrence period

  • Model 7 or 8 — PaymentPlanAmount stored; BudgetWorkAmount derived.

  • Model 7 (continuous service) — 37633 when round(amount / months, 2) differs from the contract's allocated budget amount — 'You must allocate all revenue amount to proceed.'

  • Omitted — 0 is applied (non-nullable).

Not yet documented: constraints → unit.

Responses

Propertiesobject

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).

Linksarray
Actionsobject[]