ProjectsCreate a payment on a contract

Create a payment on a contract

Adds an instalment to a contract's billing plan and returns it.

Adds a payment (instalment to invoice) to a fixed-price, time-and-material account-end-balancing, prepaid-services or task-driven-revenue contract of the project, then saves the project's billing plan. Answers 200 with the new payment (PaymentRead). On task-driven-revenue contracts a payment can be linked to a task and flagged as the task's fixed-price instalment — which unlinks the task's other instalments (see side effects).

Use it to:

  • Import a payment plan from an ERP or quote tool

Rules across fields:

  • R1: ProjectSubContractID must be a contract of ProjectID (checked during body validation).
  • R2: The contract must be FixedPriceBasic, TimeMaterialAccountEndBalancing, PrepaidServices or TaskDrivenRevenue (400).
  • R3: TaskID and IsFixedPricePayment only on a TaskDrivenRevenue contract (400); a TaskID must be on the contract.

Behaviour:

  • Not idempotent.
  • Not safe to retry blindly. Every call adds a new instalment; nothing deduplicates. After a lost response, list the contract's payments before retrying.
  • Side effect: Adds the instalment (InstallmentType 1 for fixed-price contracts, else 3; product number defaulted when the feature is on) and saves the whole billing plan through ProjectManager.Save.
  • Side effect: IsFixedPricePayment = true: every OTHER instalment of the project with the same TaskID loses its task link (TaskID → null) and its fixed-price flag.
  • Side effect: Per saved payment: payment budget periods (recurrence contracts), contract payment-plan amount sync (fixed-price / task-driven), invoicing-potential and registration-currency notifications, contract pending-booking status refresh.
  • Changes are visible to the next read immediately.

Call first: GET /v1/project/get-all, POST /v1/payment/validate-new-payment

Next: GET /v1/payment/{paymentID}, GET /v1/payment

Not yet documented: behaviour → events emitted; behaviour → side effects on failure; examples; request → body.

curl -X POST "https://app3.timelog.com/your-account/api/v1/payment" \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer YOUR_API_TOKEN" \
  -d '{
  "Name": "John Doe",
  "Comment": "example_string",
  "Amount": 3.14,
  "InvoiceDate": "2024-12-25T10:00:00Z",
  "IsReadyForInvoicing": true,
  "ProjectID": 123,
  "TaskID": 123,
  "ProductNumber": "example_string",
  "DiscountPercentage": 3.14,
  "ProjectSubContractID": 123,
  "Quantity": 3.14,
  "IsFixedPricePayment": true,
  "UnitType": 42
}'
{
  "Properties": {
    "Name": "John Doe",
    "PaymentID": 123,
    "PaymentGuid": "123e4567-e89b-12d3-a456-426614174000",
    "Comment": "example_string",
    "Amount": 3.14,
    "InvoiceDate": "2024-12-25T10:00:00Z",
    "IsReadyForInvoicing": true,
    "InstallmentType": 42,
    "ProjectID": 123,
    "TaskID": 123,
    "ProductNumberID": 123,
    "Discount": 3.14,
    "ProjectSubContractID": 123,
    "Quantity": 3.14,
    "UnitType": 42,
    "Rate": 3.14,
    "IsFixedPricePayment": true,
    "ExpensesCost": 3.14
  },
  "Links": [
    {
      "Href": "example_string",
      "Rel": "example_string"
    }
  ],
  "Actions": [
    {}
  ]
}
POST
/v1/payment
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
Namestring
Required

Instalment name.

Commentstring

Free-text comment.

Amountnumber

Instalment amount, in the project currency. Unit: project currency > Not yet documented: description.

Format: double
InvoiceDatestring
Required

Date the instalment is due for invoicing. Time zone: not yet documented. > Not yet documented: constraints → timezone.

Format: date-time
IsReadyForInvoicingboolean

Release the instalment for invoicing immediately.

ProjectIDinteger
Required

The project. Must exist (37014) and be accessible to the caller (403). Refers to ProjectRead.ProjectID. Look up valid values with GET /v1/project/get-all. Valid values come from GET /v1/project/get-all.

Format: int32
TaskIDinteger

Task to link the instalment to; only allowed (non-zero) on a task-driven-revenue contract, and the task must be on that contract (37949). 0 = none. Conditional. Must be 0 unless the contract is TaskDrivenRevenue (400 "TaskID can only be added when importing on a Task Driven Revenue Contract."). Refers to TaskRead.TaskID.

Format: int32
ProductNumberstring

Product number TEXT (not an ID). Only used when the InvoiceSetting_ProductNoActive feature is on: a supplied value must exist in the project's legal entity (37939); empty = the default product number for payments (fixed-price contracts: the project's fixed-price product number). Refers to ProductNumberRead.ProductNumber. - Feature InvoiceSetting_ProductNoActive is off — Stored as empty. - Empty and feature on — defaulted

DiscountPercentagenumber

Discount in percent. Unit: percent

Format: double
ProjectSubContractIDinteger
Required

The contract. Must belong to ProjectID (37042, raised inside model validation) and be FixedPriceBasic, TimeMaterialAccountEndBalancing, PrepaidServices or TaskDrivenRevenue (400 "The selected contract does not support import of payment."). Refers to ContractRead.ProjectSubContractID.

Format: int32
Quantitynumber

Quantity in UnitType units. Unit: UnitType

Format: double
IsFixedPricePaymentboolean

Make this the fixed-price instalment of TaskID. Only allowed on a task-driven-revenue contract (400 otherwise). Conditional. Must be false unless the contract is TaskDrivenRevenue.

UnitTypeinteger

Unit of Quantity. - Value not in the enum (e.g. 5) — 400. Allowed values: | Value | Name | Meaning | |---|---|---| | 0 | Undefined | No unit. | | 1 | Hours | Hours. | | 2 | Minutes | Minutes. | | 3 | Days | Days. | | 4 | Km | Kilometres. | | 6 | Pieces | Pieces. | | 7 | Liters | Litres. | | 8 | Meters | Metres. | | 9 | Kilograms | Kilograms. |

Format: int32 • Options: 0, 1, 2, 3, 4, 6, 7, 8, 9
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
Namestring
Required

Instalment name.

Commentstring

Free-text comment.

Amountnumber

Instalment amount, in the project currency.

Unit: project currency

Not yet documented: description.

InvoiceDatestring
Required

Date the instalment is due for invoicing.

Time zone: not yet documented.

Not yet documented: constraints → timezone.

IsReadyForInvoicingboolean

Release the instalment for invoicing immediately.

ProjectIDinteger
Required

The project. Must exist (37014) and be accessible to the caller (403).

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

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

TaskIDinteger

Task to link the instalment to; only allowed (non-zero) on a task-driven-revenue contract, and the task must be on that contract (37949). 0 = none.

Conditional. Must be 0 unless the contract is TaskDrivenRevenue (400 "TaskID can only be added when importing on a Task Driven Revenue Contract.").

Refers to TaskRead.TaskID.

ProductNumberstring

Product number TEXT (not an ID). Only used when the InvoiceSetting_ProductNoActive feature is on: a supplied value must exist in the project's legal entity (37939); empty = the default product number for payments (fixed-price contracts: the project's fixed-price product number).

Refers to ProductNumberRead.ProductNumber.

  • Feature InvoiceSetting_ProductNoActive is off — Stored as empty.

  • Empty and feature on — defaulted

DiscountPercentagenumber

Discount in percent.

Unit: percent

ProjectSubContractIDinteger
Required

The contract. Must belong to ProjectID (37042, raised inside model validation) and be FixedPriceBasic, TimeMaterialAccountEndBalancing, PrepaidServices or TaskDrivenRevenue (400 "The selected contract does not support import of payment.").

Refers to ContractRead.ProjectSubContractID.

Quantitynumber

Quantity in UnitType units.

Unit: UnitType

IsFixedPricePaymentboolean

Make this the fixed-price instalment of TaskID. Only allowed on a task-driven-revenue contract (400 otherwise).

Conditional. Must be false unless the contract is TaskDrivenRevenue.

UnitTypeinteger

Unit of Quantity.

  • Value not in the enum (e.g. 5) — 400.

Allowed values:

ValueNameMeaning
0UndefinedNo unit.
1HoursHours.
2MinutesMinutes.
3DaysDays.
4KmKilometres.
6PiecesPieces.
7LitersLitres.
8MetersMetres.
9KilogramsKilograms.
Allowed values:012346789

Responses

Propertiesobject

One billing-plan instalment of a contract: what will be invoiced (name, quantity × rate less discount = amount), when (InvoiceDate), on which project / contract / task, and whether it is ready for invoicing. The TAF self link points to GET /v1/payment/{PaymentID}; each entity also lists the six payment TAF actions.

Linksarray
Actionsobject[]