Unofficial JavaScript/TypeScript SDK for Clockodo.
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://www.clockodo.com/en/api/ "Client identification"
// PLEASE NOTE: name + ";" + email must not be longer than 50 characters.
name: "Your application/company",
email: "[email protected]",
},
authentication: {
user: "[email protected]",
// You can get your API key from https://my.clockodo.com/en/users/editself
apiKey: "kjfdskj643fgnlksf343kdslm",
},
});
client
: Specify aname
and anemail
for theX-Clockodo-External-Application
headerauthentication
: Specify auser
and anapiKey
to authenticate every requestbaseUrl
: Points to the Clockodo API. Defaults tohttps://my.clockodo.com/api
You can update the configuration later like this:
clockodo.api.config({
authentication: {
/* ... */
},
});
We have provided methods for each of the endpoints available by the Clockodo API. In order to provide a seamless API to JavaScript, we renamed the request and response object keys from what you will see in the Clockodo docs by removing special characters and converting to camel casing. If you are interested, you can find the mappings in the mappings.ts file.
For any questions about the different properties please consult the official Clockodo-API.
Some constants are also available for import:
import { EntryType, Billability, AbsenceStatus, AbsenceType } 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.
Gets a selected absence by its ID.
await clockodo.getAbsence({ id: 7 });
Gets a user's (readonly) access rights for customers and projects.
await clockodo.getUsersAccessCustomersProjects({ usersId: 67325 });
Gets a user's (readonly) access rights for services.
await clockodo.getUsersAccessServices({ usersId: 67325 });
Gets a list of absences in the provided year
await clockodo.getAbsences({ year: 2018 });
Get currently running entry for the credentials attached to Clockodo object.
await clockodo.getClock();
Get specific customer by ID
await clockodo.getCustomer({ id: 777 });
Get all customers from all pages.
await clockodo.getCustomers();
// or
await clockodo.getCustomers({
// Filter by active flag
filterActive: true,
});
Get all customers from a specific page.
await clockodo.getCustomersPage({ page: 2 });
Get an entry by its ID.
await clockodo.getEntry({ id: 4 });
Get all entries from all pages.
import { Billability } from "clockodo";
await clockodo.getEntries({
// timeSince and timeUntil are required
timeSince: "2017-08-18T00:00:00Z",
timeUntil: "2018-02-09T00:00:00Z",
// You can also add additional filters here
filterBillable: Billability.Billed,
});
Get all entries from a specific page
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.
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.
await clockodo.getEntriesTexts({ text: "meeting with client" });
Retreive all descriptions from a specific page.
await clockodo.getEntriesTextsPage({ text: "meeting with client", page: 2 });
Get a project by its ID.
await clockodo.getProject({ id: 1985 });
Get all projects from all pages.
await clockodo.getProjects();
// or
await clockodo.getProjects({
// Filter by a specific customer id
filterCustomersId: 123,
// Filter by active flag
filterActive: true,
});
Get all projects from a specific page.
await clockodo.getProjectsPage({ page: 2 });
Get a service by its ID.
await clockodo.getService({ id: 10 });
Get list of all services
await clockodo.getServices();
Get team by id.
await clockodo.getTeam({ id: 10 });
Get list of all teams.
await clockodo.getTeams();
Get a lumpsum service by its ID.
await clockodo.getLumpSumService({ id: 10 });
Get a list of all lumpsum services
await clockodo.getLumpSumServices();
Get a specific target hour period for a specific user by its ID (not the ID of the user)
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.
await clockodo.getTargethours();
// or
await clockodo.getTargethours({ usersId: 346923 });
Get a co-worker by their ID.
await clockodo.getUser({ id: 1263 });
Get list of users
await clockodo.getUsers();
Get a co-worker by their ID.
await clockodo.getUserReport({ usersId: 1263, year: 2017 });
Get an employee/user's report, which contains data such as hours worked and holidays taken.
await clockodo.getUserReports({ year: 2017, type: 1 });
With this resource you can read all nonbusiness groups. The editing and adding of nonbusiness groups is currently not possible.
await clockodo.getNonbusinessGroups();
With this resource you can read all nonbusiness days. The editing and adding of nonbusiness days is currently not possible.
await clockodo.getNonbusinessDays({
nonbusinessgroupsId: 123,
year: 2021,
});
With this resource you can read user and company seetings for the logged in user. Editing is currently not possible.
await clockodo.getAggregatesUsersMe();
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.
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.
await clockodo.addCustomer({ name: "Weyland-Yutani" });
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 |
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.
await clockodo.addProject({ name: "Clockodo Api Wrapper", customersId: 1 });
Adds to the list of services offered by your organization.
await clockodo.addService({ name: "Thinking" });
Creates a new team under your organization.
await clockodo.addTeam({ name: "Gold Team" });
Creates new user in organization.
import { UserRole } from "clockodo";
await clockodo.addUser({
name: "Merkel",
number: "08",
email: "[email protected]",
role: UserRole.Owner,
});
Start a new running clockodo entry.
import { Billability } from "clockodo";
await clockodo.startClock({
customersId: 24,
servicesId: 7,
projectsId: 365,
billable: Billability.Billable,
});
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().
await clockodo.changeClockDuration({
entriesId: 7082,
duration: 540,
durationBefore: 300,
});
Edit existing Clockodo absence.
await clockodo.editAbsence({ id: 74, note: "I know what he did last summer" });
Edit existing Clockodo customer.
await clockodo.editCustomer({ id: 15, name: "The Mystery Gang" });
Changes the values of a Clockodo entry. Unlike changeClockDuration(), editEntry() can seemingly mutate any of the accepted parameters even when the entry is running.
await clockodo.editEntry({ id: 365, duration: 540 });
Allows for mass edit of entries based on a set of filters.
import { Billability } from "clockodo";
await clockodo.editEntryGroup({
timeSince: "2017-08-18T00:00:00Z",
timeUntil: "2018-02-09T00:00:00Z",
filterText: "Browsing Reddit",
billable: Billability.NotBillable,
});
Edit existing project.
await clockodo.editProject({ id: 20, name: "Awesome new project" });
Edit existing service.
await clockodo.editService({ id: 23, name: "Room Service" });
Edit existing team.
await clockodo.editTeam({ id: 6324, name: "New Team Name" });
Edit existing user.
await clockodo.editUser({ id: 33, name: "Moalo Loco" });
Deletes the customer.
await clockodo.deleteCustomer({ id: 343 });
Deletes the project.
await clockodo.deleteProject({ id: 8 });
Deletes the service.
await clockodo.deleteService({ id: 94 });
Deletes user.
await clockodo.deleteUser({ id: 7 });
Deletes absence (go figure).
await clockodo.deleteAbsence({ id: 31 });
Deletes a single entry by ID
await clockodo.deleteEntry({ id: 543512 });
Deletes a team by ID
await clockodo.deleteTeam({ id: 764 });
Deletes one or more entries based on a series of filters that builds an "entry group".
await clockodo.deleteEntryGroup({
timeSince: "2017-08-18T00:00:00Z",
timeUntil: "2018-02-09T00:00:00Z",
text: "chilin everyday",
});
Creates a new clockodo account.
await clockodo.register({
companiesName: "Acme Corporation",
name: "Road Runner",
email: "[email protected]",
});
Stops a running clock/entry.
await clockodo.stopClock({ entriesId: 7082 });
await clockodo.stopClock({ entriesId: 7082, usersId: 123 });
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.
MIT