Skip to content

peerigon/clockodo

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1,039 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Clockodo

Unofficial JavaScript/TypeScript SDK for Clockodo.

Version on NPM Semantically released Monthly downloads on NPM
NPM Bundle size minified NPM Bundle size minified and gzipped
License

Installation and usage

npm install clockodo

For the constructor arguments, you must get the user (email) and clockodo API key from the "My area" section of Clockodo's website.

import { Clockodo } from "clockodo";

const clockodo = new Clockodo({
  client: {
    // You need to add some information about yourself that will be
    // sent along every request,
    // see https://docs.clockodo.com/#section/Clockodo-REST-API/Client-identification
    // PLEASE NOTE: name + ";" + email must not be longer than 50 characters.
    name: "Your application/company",
    email: "technical-contact@your-company.com",
  },
  authentication: {
    user: "test-user@example.com",
    // You can get your API key from https://my.clockodo.com/en/users/editself
    apiKey: "kjfdskj643fgnlksf343kdslm",
  },
});

Config

  • client: Specify a name and an email for the X-Clockodo-External-Application header
  • authentication: Specify a user and an apiKey to authenticate every request
  • baseUrl: Points to the Clockodo API. Defaults to https://my.clockodo.com/api

You can update the configuration later like this:

clockodo.api.config({
  authentication: {
    /* ... */
  },
});

API

We provide methods for Clockodo endpoints and normalize payload keys automatically: query params and request bodies are mapped from camelCase to snake_case (deeply), response bodies are mapped from snake_case to camelCase (deeply), and empty query values (undefined, null, "") are omitted. You can find the implementation in src/lib/mappings.ts.

For any questions about the different properties please consult the official Clockodo API documentation.

Some constants are also available for import:

import { AbsenceStatus, AbsenceType, Billability, EntryType } from "clockodo";

console.log(EntryType.Time); // 1
console.log(EntryType.LumpsumValue); // 2
console.log(EntryType.LumpsumService); // 3

console.log(Billability.NotBillable); // 0
console.log(Billability.Billable); // 1
console.log(Billability.Billed); // 2

Checkout models for more constants and TypeScript types.


Get Methods

Gets a selected absence by its ID.

Example:

await clockodo.getAbsence({ id: 7 });

Gets a user's (readonly) access rights for customers and projects.

Example:

await clockodo.getUsersAccessCustomersProjects({ usersId: 67325 });

Gets a user's (readonly) access rights for services.

Example:

await clockodo.getUsersAccessServices({ usersId: 67325 });

Gets a list of absences in the provided year

Example:

await clockodo.getAbsences({ year: 2018 });

Get currently running entry for the credentials attached to Clockodo object.

Example:

await clockodo.getClock();

Get specific customer by ID

Example:

await clockodo.getCustomer({ id: 777 });

Get all customers from all pages.

Example:

await clockodo.getCustomers();
// or
await clockodo.getCustomers({
  filter: {
    // Filter by active flag
    active: true,
  },
});

Get all customers from a specific page.

Example:

await clockodo.getCustomersPage({ page: 2 });

Get an entry by its ID.

Example:

await clockodo.getEntry({ id: 4 });

splitAllEntriesAtMidnight()

Splits all entries for a given user and day at midnight.

Example:

await clockodo.splitAllEntriesAtMidnight({
  day: "2026-02-17",
  usersId: 123,
});

Get all entries from all pages.

Example:

import { Billability } from "clockodo";

await clockodo.getEntries({
  // timeSince and timeUntil are required
  timeSince: "2017-08-18T00:00:00Z",
  timeUntil: "2018-02-09T00:00:00Z",
  filter: {
    // You can also add additional filters here
    billable: Billability.Billed,
  },
});

Get all entries from a specific page

Example:

await clockodo.getEntriesPage({
  timeSince: "2017-08-18T00:00:00Z",
  timeUntil: "2018-02-09T00:00:00Z",
  page: 2,
});

Get a group of entries defined by your criteria.

Example:

await clockodo.getEntryGroups({
  timeSince: "2017-08-18T00:00:00Z",
  timeUntil: "2018-02-09T00:00:00Z",
  grouping: ["customersId", "projectsId"],
  roundToMinutes: 15,
});

Retreive all descriptions (and no additional info) entered for time and lump sum entries from all pages.

Example:

await clockodo.getEntriesTexts({ term: "meeting with client" });

Retreive all descriptions from a specific page.

Example:

await clockodo.getEntriesTextsPage({ term: "meeting with client", page: 2 });

Get a project by its ID.

Example:

await clockodo.getProject({ id: 1985 });

Get all projects from all pages.

Example:

await clockodo.getProjects();
// or
await clockodo.getProjects({
  filter: {
    // Filter by a specific customer id
    customersId: 123,
    // Filter by active flag
    active: true,
  },
});

Get all projects from a specific page.

Example:

await clockodo.getProjectsPage({ page: 2 });

Get all project report rows from all pages.

Example:

await clockodo.getProjectsReports();

Get project report rows from a specific page.

Example:

await clockodo.getProjectsReportsPage({ page: 2 });

Get a subproject by its ID.

Example:

await clockodo.getSubproject({ id: 11 });

Get all subprojects from all pages.

Example:

await clockodo.getSubprojects();

Get all subprojects from a specific page.

Example:

await clockodo.getSubprojectsPage({ page: 2 });

Get a service by its ID.

Example:

await clockodo.getService({ id: 10 });

Get list of all services

Example:

await clockodo.getServices();

Get a list of services from a specific page.

Example:

await clockodo.getServicesPage({ page: 2 });

Get team by id.

Example:

await clockodo.getTeam({ id: 10 });

Get list of all teams.

Example:

await clockodo.getTeams();

Get a lumpsum service by its ID.

Example:

await clockodo.getLumpSumService({ id: 10 });

Get a list of all lumpsum services

Example:

await clockodo.getLumpSumServices();

Get a list of lumpsum services from a specific page.

Example:

await clockodo.getLumpSumServicesPage({ page: 2 });

Get a specific target hour period for a specific user by its ID (not the ID of the user)

Example:

await clockodo.getTargethoursRow({ id: 1234 });

Get list of target hours for all users, with option to pass an object with an usersId to filter the history of target hours to a specific user.

Example:

await clockodo.getTargethours();
// or
await clockodo.getTargethours({ usersId: 346923 });

Get a co-worker by their ID.

Example:

await clockodo.getUser({ id: 1263 });

Get list of users

Example:

await clockodo.getUsers();

getSurchargeModel()

Get a surcharge model by ID.

Example:

await clockodo.getSurchargeModel({ id: 7 });

getSurchargeModels()

Get all surcharge models.

Example:

await clockodo.getSurchargeModels();

Get a report for a specific user and year.

Example:

await clockodo.getUserReport({ usersId: 1263, year: 2017 });

Get an employee/user's report, which contains data such as hours worked and holidays taken.

Example:

await clockodo.getUserReports({ year: 2017, type: 1 });

Gets all nonbusiness groups.

Example:

await clockodo.getNonbusinessGroups();

Gets a nonbusiness group by ID.

Example:

await clockodo.getNonbusinessGroup({ id: 123 });

Gets all nonbusiness days for a given year.

Example:

await clockodo.getNonbusinessDays({
  nonbusinessGroupId: 123,
  year: 2021,
});

Gets a nonbusiness day by ID.

Example:

await clockodo.getNonbusinessDay({ id: 12, year: 2026 });

Gets user and company settings for the logged-in user.

Example:

await clockodo.getMe();

Gets work times from a specific page.

Example:

await clockodo.getWorkTimesPage({
  usersId: 123,
  dateSince: "2026-02-01",
  dateUntil: "2026-02-07",
  page: 2,
});

Gets all work time pages for the given filter.

Example:

await clockodo.getWorkTimes({
  usersId: 123,
  dateSince: "2026-02-01",
  dateUntil: "2026-02-07",
});

Gets work time change requests from a specific page.

Example:

await clockodo.getWorkTimesChangeRequestsPage({
  usersId: 123,
  dateSince: "2026-02-01",
  dateUntil: "2026-02-07",
  page: 2,
});

Gets all work time change request pages for the given filter.

Example:

await clockodo.getWorkTimesChangeRequests({
  usersId: 123,
  dateSince: "2026-02-01",
  dateUntil: "2026-02-07",
});

Gets overtime carry rows.

Example:

await clockodo.getOvertimecarry({ usersId: 17, year: 2028 });

Gets an overtime carry row by ID.

Example:

await clockodo.getOvertimecarryRow({ id: 7 });

Gets holiday quota rows.

Example:

await clockodo.getHolidaysQuotas({ usersId: 17, year: 2028 });

Gets a holiday quota row by ID.

Example:

await clockodo.getHolidaysQuota({ id: 7 });

Gets holiday carryover rows.

Example:

await clockodo.getHolidaysCarryovers({ usersId: 17, year: 2028 });

Gets a holiday carryover row by ID.

Example:

await clockodo.getHolidaysCarryover({ id: 7 });

Post Methods

Default behavior adds an absence for the user attached to the credentials given to the clockodo object. To add the absence for another user you can use the usersId option if you have the permissions.

Example:

import { AbsenceType } from "clockodo";

await clockodo.addAbsence({
  dateSince: "2017-08-18T00:00:00Z",
  dateUntil: "2018-02-09T00:00:00Z",
  type: AbsenceType.SpecialLeave,
  note: "elternzeit",
  usersId: 12321,
});

Adds a customer to the organization.

Example:

await clockodo.addCustomer({ name: "Weyland-Yutani" });

Adds a lumpsum service.

Example:

await clockodo.addLumpsumService({ name: "Flat Rate Support", price: 99 });

Creates a nonbusiness group.

Example:

await clockodo.addNonbusinessGroup({ name: "NRW", preset: "" });

Creates a nonbusiness day.

Example:

await clockodo.addNonbusinessDay({
  nonbusinessGroupId: 2,
  type: "DISTINCT_ONCE",
  name: "Labor Day",
});

Creates an overtime carry row.

Example:

await clockodo.addOvertimecarry({
  usersId: 17,
  year: 2028,
  hours: 8,
  note: "carryover",
});

Creates a holidays quota row.

Example:

await clockodo.addHolidaysQuota({
  usersId: 17,
  yearSince: 2028,
  count: 30,
});

Creates a holidays carryover row.

Example:

await clockodo.addHolidaysCarryover({
  usersId: 17,
  year: 2028,
  count: 5,
});

Creates an entry for either the user attached to the Clockodo instance or the passed in usersId. Depending on the type of entry different properties are required:

Type of entry Required properties
Manual time entry customersId, servicesId, billable, timeSince, timeUntil
Lumpsum value entry customersId, servicesId, billable, timeSince, lumpsum
Lumpsum service entry customersId, lumpsumServicesAmount, lumpsumServicesId, billable, timeSince

Example:

import { Billability } from "clockodo";

await clockodo.addEntry({
  customersId: 1,
  servicesId: 2,
  billable: Billability.Billable,
  timeSince: "2018-10-01T00:00:00Z",
  timeUntil: "2018-10-01T03:00:00Z",
});

Creates a project for an existing customer.

Example:

await clockodo.addProject({ name: "Clockodo Api Wrapper", customersId: 1 });

Creates a subproject for an existing project.

Example:

await clockodo.addSubproject({ projectsId: 1, name: "SDK Migration" });

Adds to the list of services offered by your organization.

Example:

await clockodo.addService({ name: "Thinking" });

Creates a new team under your organization.

Example:

await clockodo.addTeam({ name: "Gold Team" });

Creates new user in organization.

Example:

import { UserRole } from "clockodo";

await clockodo.addUser({
  name: "Merkel",
  number: "08",
  email: "angela@eu.eu",
  role: UserRole.Owner,
});

addSurchargeModel()

Adds a surcharge model.

Example:

await clockodo.addSurchargeModel({ name: "Night Shift", accumulation: true });

Start a new running clockodo entry.

Example:

import { Billability } from "clockodo";

await clockodo.startClock({
  customersId: 24,
  servicesId: 7,
  projectsId: 365,
  billable: Billability.Billable,
});

Creates a work time change request.

Example:

import { WorkTimeChangeRequestIntervalType } from "clockodo";

await clockodo.addWorkTimesChangeRequest({
  date: "2026-02-17",
  usersId: 123,
  changes: [
    {
      type: WorkTimeChangeRequestIntervalType.Add,
      timeSince: "2026-02-17T08:00:00Z",
      timeUntil: "2026-02-17T12:00:00Z",
    },
  ],
});

Approves a work time change request by ID.

Example:

await clockodo.approveWorkTimesChangeRequest({ id: 17 });

Declines a work time change request by ID.

Example:

await clockodo.declineWorkTimesChangeRequest({ id: 17 });

Put methods

Changes the duration of an entry. Because the ID returned by clock methods is just the entry ID, and this function can only be used after an entry is finished, there seems to be no difference from using editEntry().

Example:

await clockodo.changeClockDuration({
  entriesId: 7082,
  duration: 540,
  durationBefore: 300,
});

Edit existing Clockodo absence.

Example:

await clockodo.editAbsence({ id: 74, note: "I know what he did last summer" });

Edit existing Clockodo customer.

Example:

await clockodo.editCustomer({ id: 15, name: "The Mystery Gang" });

Edit an existing lumpsum service.

Example:

await clockodo.editLumpsumService({ id: 15, name: "Updated Flat Rate" });

Changes the values of a Clockodo entry. Unlike changeClockDuration(), editEntry() can seemingly mutate any of the accepted parameters even when the entry is running.

Example:

await clockodo.editEntry({ id: 365, duration: 540 });

Allows for mass edit of entries based on a set of filters.

Example:

import { Billability } from "clockodo";

await clockodo.editEntryGroup({
  timeSince: "2017-08-18T00:00:00Z",
  timeUntil: "2018-02-09T00:00:00Z",
  filter: {
    text: "Browsing Reddit",
    billable: Billability.NotBillable,
  },
});

Edit existing project.

Example:

await clockodo.editProject({ id: 20, name: "Awesome new project" });

Set a project's completion status.

Example:

await clockodo.completeProject({ id: 20, completed: true });

Set a project's billed status and billed amount.

Example:

await clockodo.setProjectBilled({ id: 20, billed: true, billedMoney: 1234.5 });

Edit existing subproject.

Example:

await clockodo.editSubproject({ id: 20, name: "SDK Migration Phase 2" });

Set a subproject's completion status.

Example:

await clockodo.completeSubproject({ id: 20, completed: true });

Edit existing service.

Example:

await clockodo.editService({ id: 23, name: "Room Service" });

Edit existing team.

Example:

await clockodo.editTeam({ id: 6324, name: "New Team Name" });

Edit existing user.

Example:

await clockodo.editUser({ id: 33, name: "Moalo Loco" });

editSurchargeModel()

Edit an existing surcharge model.

Example:

await clockodo.editSurchargeModel({ id: 365, name: "ABC" });

Edits a nonbusiness group.

Example:

await clockodo.editNonbusinessGroup({ id: 2, name: "Holidays" });

Edits a nonbusiness day.

Example:

await clockodo.editNonbusinessDay({
  id: 2,
  name: "Holiday",
  type: "DISTINCT_RECURRING",
});

Edits an overtime carry row.

Example:

await clockodo.editOvertimecarry({ id: 2, hours: 8, note: "updated" });

Edits a holidays quota row.

Example:

await clockodo.editHolidaysQuota({ id: 2, count: 25, note: "updated" });

Edits a holidays carryover row.

Example:

await clockodo.editHolidaysCarryover({ id: 2, count: 5, note: "updated" });

Delete methods

Deletes the customer.

Example:

await clockodo.deleteCustomer({ id: 343 });

Deletes the project.

Example:

await clockodo.deleteProject({ id: 8 });

Deletes the subproject.

Example:

await clockodo.deleteSubproject({ id: 8 });

Deletes the service.

Example:

await clockodo.deleteService({ id: 94 });

Deletes user.

Example:

await clockodo.deleteUser({ id: 7 });

deleteSurchargeModel()

Deletes a surcharge model by ID.

Example:

await clockodo.deleteSurchargeModel({ id: 31 });

Deletes absence (go figure).

Example:

await clockodo.deleteAbsence({ id: 31 });

Deletes a single entry by ID

Example:

await clockodo.deleteEntry({ id: 543512 });

Deletes a lumpsum service by ID.

Example:

await clockodo.deleteLumpsumService({ id: 94 });

Deletes a team by ID

Example:

await clockodo.deleteTeam({ id: 764 });

Deletes a nonbusiness group by ID.

Example:

await clockodo.deleteNonbusinessGroup({ id: 31 });

Deletes a nonbusiness day by ID.

Example:

await clockodo.deleteNonbusinessDay({ id: 31 });

Deletes an overtime carry row by ID.

Example:

await clockodo.deleteOvertimecarry({ id: 31 });

Deletes a holidays quota row by ID.

Example:

await clockodo.deleteHolidaysQuota({ id: 31 });

Deletes a holidays carryover row by ID.

Example:

await clockodo.deleteHolidaysCarryover({ id: 31 });

Deletes one or more entries based on a series of filters that builds an "entry group".

Example:

await clockodo.deleteEntryGroup({
  timeSince: "2017-08-18T00:00:00Z",
  timeUntil: "2018-02-09T00:00:00Z",
  text: "chilin everyday",
});

Withdraws a work time change request by ID.

Example:

await clockodo.withdrawWorkTimesChangeRequest({ id: 17 });

Creates a new clockodo account.

Example:

await clockodo.register({
  companiesName: "Acme Corporation",
  name: "Road Runner",
  email: "runner@acme.com",
});

Stops a running clock/entry.

Example for self:

await clockodo.stopClock({ entriesId: 7082 });

Example for another user (needs requesting user to be owner):

await clockodo.stopClock({ entriesId: 7082, usersId: 123 });

Development

To run integration tests you need to create an .env by copying the .env.example and entering credentials of a dev-user, as you don't want to mess up your real clockodo data.

License

MIT

Sponsors

About

Unofficial JavaScript/TypeScript SDK for Clockodo

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 17

Languages