Hourtick Notes and files API

Documents and files on a client or a project. Everyone in the workspace can read and add them; the author or a manager deletes. Notes are Tiptap JSON with a plain-text copy (`text`); saves carry a `version` and a stale one answers 409.

Operations 10

GET /api/v1/notes Notes on a project (`projectId`) or client (`clientId`): titles and previews… #
POST /api/v1/notes Create a note on a project or client #
GET /api/v1/notes/{id} One note: title, Tiptap `content`, `markdown`, plain `text` and `version` #
PATCH /api/v1/notes/{id} Save a note #
DELETE /api/v1/notes/{id} Delete a note (its creator or a manager) #
GET /api/v1/files Files on a project (`projectId`) or client (`clientId`), newest first #
POST /api/v1/files Upload a file to a project or client (multipart: file, projectId or clientId… #
GET /api/v1/files/{id} Open a file: redirects to a short-lived signed URL (`?download=1` to download… #
DELETE /api/v1/files/{id} Delete a file (its uploader or a manager) #
GET /api/v1/records/counts Notes and files per project and client #

Work with this as data

Every API here is available over the APIs.io API and to AI agents over MCP.

MCP server

One button, every client — Claude, Cursor, VS Code and the rest.

https://apis.io/mcp

Tools for apis

7 MCP tools reach this
  • find_apisBrowse and filter every API in the catalog.
  • get_api_artifactsOne API's artifacts, grouped by type.
  • get_openapiThe primary OpenAPI for this API.
  • find_similar_apisAPIs that look like this one.
  • apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
  • resolveTurn a domain, URL or GitHub org into the provider it belongs to.
  • find_cohortsEvery scored population of providers in the catalog.
All 92 tools →

Call it yourself

curl for this page
This API
curl "https://apis.io/api/v1/apis/hourtick:hourtick-notes-and-files-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"

Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.

Get an API key

Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.

A second provider on the same verified email joins the account you already have.

OpenAPI Specification

hourtick-notes-and-files-api-openapi.yml Raw ↑
openapi: 3.2.0
info:
  title: Hourtick Notes and files API
  version: 1.0.0
  description: 'The Hourtick REST API. Authenticate with a personal API token: create one in **Settings → API tokens**, then send `Authorization: Bearer ht_…`.


    All timer changes go through **POST /api/v1/commands**, the same endpoint the web and Mac apps use. Commands are idempotent per `commandId` (use a new UUID per action, reuse it to retry safely).


    Every response carries a `Server-Time` header (epoch ms). Errors use RFC 9457 problem details.'
servers:
- url: https://hourtick.com
security:
- bearer: []
tags:
- name: Notes and files
  description: Documents and files on a client or a project. Everyone in the workspace can read and add them; the author or a manager deletes. Notes are Tiptap JSON with a plain-text copy (`text`); saves carry a `version` and a stale one answers 409.
paths:
  /api/v1/notes:
    get:
      tags:
      - Notes and files
      summary: 'Notes on a project (`projectId`) or client (`clientId`): titles and previews…'
      parameters:
      - name: projectId
        in: query
        schema:
          type: string
          format: uuid
      - name: clientId
        in: query
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: '{ notes: [{ id, title, preview, updatedAt, updatedBy, createdBy }] }'
      operationId: getApiV1Notes
      x-operation-id-source: derived
    post:
      tags:
      - Notes and files
      summary: Create a note on a project or client
      description: Send the document as `markdown` (easiest; headings, marks, links, lists, checklists, tables, quotes, code) or as Tiptap JSON in `content`.
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                projectId:
                  type: string
                  format: uuid
                clientId:
                  type: string
                  format: uuid
                title:
                  type: string
                  maxLength: 200
                markdown:
                  type: string
                content:
                  type: object
                  description: 'Tiptap JSON (type: doc)'
      responses:
        '201':
          description: '{ note }'
      operationId: postApiV1Notes
      x-operation-id-source: derived
  /api/v1/notes/{id}:
    get:
      tags:
      - Notes and files
      summary: 'One note: title, Tiptap `content`, `markdown`, plain `text` and `version`'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: '{ note }'
      operationId: getApiV1NotesById
      x-operation-id-source: derived
    patch:
      tags:
      - Notes and files
      summary: Save a note
      description: 'Replace the title and/or the document (`markdown` or `content`) with the `version` you started from. If someone saved since, 409 `notes/conflict` returns their `note`; resend with `force: true` to keep yours. `appendMarkdown` adds to the end of the current document and needs no version. Links other than http(s) and mailto are removed.'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              properties:
                title:
                  type: string
                markdown:
                  type: string
                appendMarkdown:
                  type: string
                content:
                  type: object
                version:
                  type: integer
                force:
                  type: boolean
      responses:
        '200':
          description: '{ note }'
        '409':
          description: Changed by someone else
      operationId: patchApiV1NotesById
      x-operation-id-source: derived
    delete:
      tags:
      - Notes and files
      summary: Delete a note (its creator or a manager)
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '204':
          description: Deleted
      operationId: deleteApiV1NotesById
      x-operation-id-source: derived
  /api/v1/files:
    get:
      tags:
      - Notes and files
      summary: Files on a project (`projectId`) or client (`clientId`), newest first
      parameters:
      - name: projectId
        in: query
        schema:
          type: string
          format: uuid
      - name: clientId
        in: query
        schema:
          type: string
          format: uuid
      responses:
        '200':
          description: '{ files: Attachment[] }'
      operationId: getApiV1Files
      x-operation-id-source: derived
    post:
      tags:
      - Notes and files
      summary: 'Upload a file to a project or client (multipart: file, projectId or clientId…'
      responses:
        '201':
          description: '{ file }'
        '402':
          description: 'Usage limit reached: uploads are paused'
      operationId: postApiV1Files
      x-operation-id-source: derived
  /api/v1/files/{id}:
    get:
      tags:
      - Notes and files
      summary: 'Open a file: redirects to a short-lived signed URL (`?download=1` to download…'
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '302':
          description: Signed URL
      operationId: getApiV1FilesById
      x-operation-id-source: derived
    delete:
      tags:
      - Notes and files
      summary: Delete a file (its uploader or a manager)
      parameters:
      - name: id
        in: path
        required: true
        schema:
          type: string
          format: uuid
      responses:
        '204':
          description: Deleted
      operationId: deleteApiV1FilesById
      x-operation-id-source: derived
  /api/v1/records/counts:
    get:
      tags:
      - Notes and files
      summary: Notes and files per project and client
      responses:
        '200':
          description: '{ projects: { [id]: { notes, files } }, clients: { … } }'
      operationId: getApiV1RecordsCounts
      x-operation-id-source: derived
components:
  securitySchemes:
    bearer:
      type: http
      scheme: bearer
      bearerFormat: ht_… personal API token