> ## Documentation Index
> Fetch the complete documentation index at: https://docs.infinity.swiss/llms.txt
> Use this file to discover all available pages before exploring further.

# Record a work entry

> Records a new work entry on a project. Work entries recorded this way appear as unbilled work on the project and can be billed from Infinity later on.

## Recording work on a project

Work entries are the individual units of work performed for a client. Recording them through the API lets an external system — for example field management software that captures hours and material expenses on site — feed a project in Infinity, so the work can be billed from Infinity later on.

The `type` field selects how the work entry is valued and which further fields are required:

| Type          | Valued by                     | Required fields                      |
| ------------- | ----------------------------- | ------------------------------------ |
| `hourly`      | An hourly rate and time spent | `rate`, `hours` (`minutes` optional) |
| `fixed-price` | A fixed amount                | `price`                              |
| `unbillable`  | Not billable                  | —                                    |

All amounts are given in cents, and `date` is the day the work was performed on, in `YYYY-MM-DD` format.

### Examples

Two and a half hours of work at an hourly rate of CHF 120.00:

```json theme={null}
{
  "type": "hourly",
  "date": "2026-03-14",
  "description": "Elektroinstallation Erdgeschoss",
  "rate": 12000,
  "hours": 2,
  "minutes": 30
}
```

Material purchased for the project, billed at a fixed CHF 450.50:

```json theme={null}
{
  "type": "fixed-price",
  "date": "2026-03-15",
  "description": "Kabelmaterial",
  "price": 45050
}
```

Work that should be documented on the project but never invoiced:

```json theme={null}
{
  "type": "unbillable",
  "date": "2026-03-16",
  "description": "Interne Besprechung"
}
```

The response returns the created work entry, including its `id` and the resulting `amount` in cents.

<Note>
  Recording a work entry does not create any invoice or booking. New work
  entries appear as unbilled work on the project and are billed from Infinity,
  where you choose which entries to include on an invoice and how they are
  presented.
</Note>


## OpenAPI

````yaml POST /v1/projects/{projectId}/work-entries
openapi: 3.1.0
info:
  title: infinity.swiss Open API
  version: '1.0'
  summary: ''
servers:
  - url: https://api.infinity.swiss
security:
  - apiKey: []
paths:
  /v1/projects/{projectId}/work-entries:
    parameters:
      - schema:
          type: string
        name: projectId
        in: path
        description: The id of the project the work entries belong to.
        required: true
    post:
      tags: []
      summary: Record a work entry
      description: >-
        Records a new work entry on a project. Work entries recorded this way
        appear as unbilled work on the project and can be billed from Infinity
        later on.
      operationId: create-work-entry-v1
      requestBody:
        description: >-
          The work entry payload. The `type` field selects which further fields
          are required.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/WorkEntryInput'
            examples:
              Hourly work:
                value:
                  type: hourly
                  date: '2024-03-14'
                  description: Elektroinstallation Erdgeschoss
                  rate: 12000
                  hours: 2
                  minutes: 30
              Material expense:
                value:
                  type: fixed-price
                  date: '2024-03-15'
                  description: Kabelmaterial
                  price: 45050
              Unbillable work:
                value:
                  type: unbillable
                  date: '2024-03-16'
                  description: Interne Besprechung
      responses:
        '201':
          description: The work entry was recorded successfully.
          content:
            application/json:
              schema:
                type: object
                properties:
                  workEntry:
                    $ref: '#/components/schemas/WorkEntry'
        '400':
          $ref: '#/components/responses/WorkEntryBadRequest'
        '401':
          $ref: '#/components/responses/Unauthorised'
        '404':
          $ref: '#/components/responses/ProjectNotFound'
components:
  schemas:
    WorkEntryInput:
      title: WorkEntryInput
      type: object
      description: >-
        Request body for recording a work entry. Which fields are required
        depends on `type`.
      required:
        - type
        - date
        - description
      properties:
        type:
          $ref: '#/components/schemas/WorkEntryType'
        date:
          type: string
          format: date
          description: The date the work was performed on, in YYYY-MM-DD format.
        description:
          type: string
          maxLength: 2000
          description: The description of the work that was performed.
        price:
          type: integer
          description: >-
            The amount in cents to invoice. Required for `fixed-price` work
            entries, must be greater than zero.
        rate:
          type: integer
          description: >-
            The hourly rate in cents. Required for `hourly` work entries, must
            be greater than zero.
        hours:
          type: integer
          description: The number of full hours spent. Required for `hourly` work entries.
        minutes:
          type: integer
          default: 0
          description: >-
            The number of minutes spent in addition to `hours`, between 0 and
            59. Optional for `hourly` work entries. The total time must be
            greater than zero.
    WorkEntry:
      title: WorkEntry
      type: object
      description: A single unit of work that was performed on a project.
      required:
        - id
        - type
        - date
        - description
        - wasBilled
      properties:
        id:
          type: string
          description: The unique id of this work entry within its project.
        type:
          $ref: '#/components/schemas/WorkEntryType'
        date:
          type: string
          format: date
          description: The date the work was performed on, in YYYY-MM-DD format.
        description:
          type: string
          description: >-
            The description of the work that was performed. Appears on the
            invoice when the work entry is billed.
        wasBilled:
          type: boolean
          description: >-
            Whether this work entry has already been billed on an invoice. This
            field is read-only and is set by Infinity when the work is billed.
        price:
          type: integer
          description: >-
            The amount in cents that can be invoiced for this work entry. Only
            present for `fixed-price` work entries.
        rate:
          type: integer
          description: >-
            The hourly rate in cents used for this work entry. Only present for
            `hourly` work entries.
        hours:
          type: integer
          description: >-
            The number of full hours spent. Only present for `hourly` work
            entries.
        minutes:
          type: integer
          description: >-
            The number of minutes spent in addition to `hours`. Only present for
            `hourly` work entries.
        amount:
          type: integer
          description: >-
            The resulting value of this work entry in cents. Not present for
            `unbillable` work entries.
    WorkEntryType:
      title: WorkEntryType
      type: string
      description: >-
        The kind of a work entry, which determines how it is valued:

        - `hourly` is valued by an hourly rate and the time spent

        - `fixed-price` is valued by a fixed amount, e.g. for materials or lump
        sum work

        - `unbillable` has no value and cannot be billed
      enum:
        - unbillable
        - fixed-price
        - hourly
  responses:
    WorkEntryBadRequest:
      description: >-
        A bad request is thrown if the work entry payload is malformed or fails
        validation.
      content:
        application/json:
          schema:
            type: object
            required:
              - code
            properties:
              code:
                type: string
                description: >-
                  The specific error code for this request. May be:

                  - `general/missing-fields` when required fields are missing or
                  malformed

                  - `general/malformed-request` when fields are sent that do not
                  belong to the work entry type

                  - `general/zero-or-negative-amount-not-allowed` when a price
                  or rate is zero or negative

                  - `projects/invalid-unbilled-work-time` when the time spent is
                  zero or the minutes are out of range
              invalidFields:
                type: array
                description: A list of the fields which were invalid, if applicable.
                items:
                  type: string
    Unauthorised:
      description: >-
        An unauthorised request was submitted. You may be using an incorrect or
        expired API token, or are attempting to access a document outside of the
        scope of the token.
      content:
        application/json:
          schema:
            type: object
            properties:
              code:
                type: string
                x-stoplight:
                  id: 08hkw8ukmi2lp
                description: Specific error code
          examples:
            Unauthorised request:
              value:
                code: general/unauthorised
    ProjectNotFound:
      description: No project with the given id could be found in this organisation.
      content:
        application/json:
          schema:
            type: object
            properties:
              code:
                type: string
                description: Specific error code.
          examples:
            Not found:
              value:
                code: projects/not-found
  securitySchemes:
    apiKey:
      name: x-api-token
      type: apiKey
      in: header
      description: >-
        API token for authentication. Obtain from your Infinity account
        settings.

````