Skip to main content

Clockbook Guide


Introduction

By using Clockbook REST-based API, you can push and pull data to and from Clockbook, and integrate it with other systems. Feel free to post any questions you have on Stack Overflow with the Clockbook tag, or contact us if something is not working properly.

To get reports via API, you're going to have to use the base endpoint for reports (which is different from the one for manipulating other objects).


Authentication

All your requests should include "X-Api-Key" in request header, containing your API key.

If your workspace is on a subdomain (eg. something.clockbook.me), you'll need to generate a new API key in your Profile Settings that will work just for that workspace.

If you're a self-hosted user, you'll have to use a different API base endpoint: "https://yourcustomdomain.com/api" and "https://yourdomain.com/reports" (you can find exact endpoints when you go to "https://youdomain.com/web/boot").

Rate limiting

There's a rate limit of 10 requests per second. If you get over the limit, you'll get "Too many requests" error.

Webhooks

Webhooks can notify your app when something happens in Clockbook. You can access webhooks from the bottom of your Profile settings

Only workspace admins can create webhooks. Only the user who created the webhook can see and modify it. Each user can have up to 10 webhooks per workspace, and a workspace can have 100 in total

You can see logs of sent webhooks by clicking on a webhook you've created. There you can send a test webhook. Logs older than 7 days are deleted.

You can find your webhook's signing secret by clicking on the webhook's eye icon Webhooks page (or when you open edit screen of the webhook). Then, to verify the webhook with the signing secret, compare it with the "Clockbook-signature" value in the response header.

You can send "Action-Metadata" parameter via API request header, and its value will be passed along by the webhook event it triggered. Example: You can send "update time entry" request and pass along "Action-Metadata: MyRequestId123" in the header, and when the "time entry updated" webhook is triggered, you'll receive "Action-Metadata: MyRequestId123" in the webhook so you can avoid endless update loop.

To test and debug webhooks, you can use an online service like Request Catcher.

Available webhooks

  • Timer started/stopped (me/anyone)
  • Time entry created manually/updated/deleted (me/anyone)
  • Client/project/task/tag created on workspace

Client

Response Content-Types: /

Response Example (200 OK)

[
{
id: "5b1e52ff0cb8792ed75992c1",
name: "Client X",
workspaceId: "5c0fe3290cl84304845dbf1f",
archived: "false",
},
];

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.


Find clients on workspace

archived: booleanIf true, you'll get only archived clients. If false, you'll get only active clients
Stillrenders
12

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.


Add a new client to workspace

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.


Update client

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.


Delete client

Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book.


Project

Emphasis, aka italics, with asterisks or underscores.

Strong emphasis, aka bold, with asterisks or underscores.

Combined emphasis with asterisks and underscores.

Strikethrough uses two tildes. Scratch this.


Get all projects on workspace

Response Content-Types: /

Response Example (200 OK)


[
{
"id": "5e4e42156fe9056cfb00252",
"name": "Project",
"hourlyRate": null,
"clientId": "",
"workspaceId": "5e4e38caq7668c16662b303a",
"billable": true,
"memberships": [
{
"userId": "5a0ab5acb2d987125438b60f",
"hourlyRate": null,
"targetId": "5e4e38f156fe9056cfb00252",
"membershipType": "PROJECT",
"membershipStatus": "ACTIVE"
}
]
"color": "#4CAF50",
"estimate": {
"estimate": "PT0S",
"type": "AUTO"
}, // Legacy field, same info as timeEstimate
"archived": false,
"duration": "PT0S",
"clientName": "",
"note": "",
"template": false,
"public": false,
"costRate": null,
"budgetEstimate": null,
"timeEstimate": {
"estimate": "PT0S",
"type": "AUTO",
"resetOption": null,
"active": true
}
}
]

Find project by ID

Response Content-Types: /

Response Example (200 OK)

{
"id": "5e4e42156fe9056cfb00252",
"name": "Project",
"hourlyRate": null,
"clientId": "",
"workspaceId": "5e4e38caq7668c16662b303a",
"billable": true,
"memberships": [
{
"userId": "5a0ab5acb2d987125438b60f",
"hourlyRate": null,
"targetId": "5e4e38f156fe9056cfb00252",
"membershipType": "PROJECT",
"membershipStatus": "ACTIVE"
}
]
"color": "#4CAF50",
"estimate": {
"estimate": "PT0S",
"type": "AUTO"
}, // Legacy field, same info as timeEstimate
"archived": false,
"duration": "PT0S",
"clientName": "",
"note": "",
"template": false,
"public": false,
"costRate": null,
"budgetEstimate": null,
"timeEstimate": {
"estimate": "PT0S",
"type": "AUTO",
"resetOption": null,
"active": true
}
}

Add a new project to workspace

Request Content-Types: application/json

Request Example

{
"name": "My API Project",
// OPTIONAL
"clientId": "",
"isPublic": "false",
"color": "#f44336",
"note": "This is project's note",
"billable": "true",
"public": false
}

Response Content-Types: /

Response Example (201 Created)

  {
"archived": "false",
"billable": "true",
"clientId": "",
"clientName": "",
"color": "string",
"duration": "PT0S",
"estimate": {
"estimate": "PT0S",
"type": "MANUAL"
}, // Legacy field, same info as timeEstimate
"hourlyRate": {
"amount": "0",
"currency": "USD"
},
"id": "5b1e6b160cb8793dd93ec120",
"memberships": [
{
"hourlyRate": {
"amount": "10",
"currency": "USD"
,
"membershipStatus": "ACTIVE",
"membershipType": "PROJECT",
"targetId": "5b1e6b160cb8793dd93ec120",
"userId": "5a9e9a39b079874a74cfa980"
}
}
],
"name": "My Api Project",
"public": false,
"costRate": null,
"budgetEstimate": null,
"timeEstimate": {
"estimate": "PT0S",
"type": "AUTO",
"resetOption": null,
"active": true
},
"workspaceId": "5b152d9b0cb8797f86cbe14f",
}

Tag

Endpoints for manipulating TAG resource


Find tags on workspace

Path

GET / workspaces / { workspaceId } / tags;

REQUEST PARAMETERS

name: string in queryIf provided, tags will be filtered by name.
archived: boolean in queryIf true, you'll get only archived tags.
If false, you'll get only active tags.
page: integer default: 1 in querypage

| page-size: integ | is-active:boolean er
default: 50 in query | page-size |

RESPONSES


200 OK OK


401 Unauthorized Unauthorized


403 Forbidden Forbidden


404 Not Found Not Found

Response Content-Types: /

Response Example (200 OK)

[
{
id: "5a7c5d2db079870147fra234",
name: "Tag 1",
workspaceId: "5g3g57bt0cb2548e22e6l9cd",
archived: "false",
},
];

Add a new tag to workspace

Request Content-Types: application/json

Request Example

{
"name": "Tag 1"
}

Response Content-Types: /

Response Example (201 Created)

{
"id": "5a7c5d2db079870147fra234",
"name": "Tag 1",
"workspaceId": "5g3g57bt0cb2548e22e6l9cd"
}

Update tag

PATH

PUT / workspaces / { workspaceId } / tags / { tagId };

RESPONSES


200 OK OK


201 Created Created


401 Unauthorized Unauthorized


403 Forbidden Forbidden


404 Not Found Not Found


Delete tag

PATH

DELETE / workspaces / { workspaceId } / tags / { tagId };

RESPONSES


200 OK OK


204 No Content Content


400 Bad Request Bad Request


401 Unauthorized Unauthorized


403 Forbidden Forbidden


404 Not Found Not Found


Task

Endpoints for manipulating TASK resource

Response Content-Types: /

Response Example (200 OK)

[
{
"assigneeIds": ["593e40aab0798735d0392a2d"],
"estimate": "PT0S",
"id": "5b1e6b160cb8793dd93ec120",
"name": "Task 1",
"projectId": "5b1667790cb8797321f3d664",
"status": "ACTIVE" (Status: ACTIVE, DONE)
}
]

Find tasks on project


PATH

GET / workspaces / { workspaceId } / projects / { projectId } / tasks;

REQUEST PARAMETERS

is-active: boolean in queryIf provided and true, only active tasks will be returned.
Otherwise only finished tasks will be returned.
name: string in queryIf provided, tasks will be filtered by name.
page: integer default: 1 in querypage
page-size: integer default: 50 in querypage-size

RESPONSES


200 OK OK


401 Unauthorized Unauthorized


403 Forbidden Forbidden


404 Not Found Not Found


Find task on project by ID


PATH

GET /
workspaces /
{ workspaceId } /
projects /
{ projectId } /
tasks /
{ taskId };

RESPONSES


200 OK OK


401 Unauthorized Unauthorized


403 Forbidden Forbidden


404 Not Found Not Found

Add a new task on project

PATH

POST /workspaces/{workspaceId}/projects/{projectId}/tasks

RESPONSES


200 OK OK


400 Bad Request Task with that name already exists
on project, or specified project
doesn't exist


401 Unauthorized Unauthorized


403 Forbidden Forbidden


404 Not Found Not Found

Time entry

Endpoints for manipulating TIMEENTRY resource

Get your time entries on workspace

Gets a time entry for specified user on workspace. Filters can be applied as query parameters listed below

Response Content-Types: /

Response Example (200 OK)

[
{
"billable": "true",
"description": "Writing documentation",
"id": "5b0fdf2a0cb87904845dfer5",
"isLocked": "false",
"projectId": "5b1667790cb8797321f3d664",
"tagIds": [
"5a7c5d2db079870147fra234"
],
"taskId": "5b1e6b160cb8793dd93ec120",
"timeInterval": {
"duration": "PT1M4S",
"end": "2018-06-12T14:01:41Z",
"start": "2018-06-12T14:00:37Z"
},
"userId": "6h1e49bf0cb8790e43d6c9ab",
"workspaceId": "5g3g57bt0cb2548e22e6l9cd"
},
"customFields": [
{
"customFieldId" : "5b1e6b160cb8793dd93ec120",
"timeEntryId" : "5c5bda4fb079871c518b6f07",
"value": "San Francisco",
"name": "Location"
}
]
]


Line Breaks

Here's a line for us to start with.

This line is separated from the one above by two newlines, so it will be a separate paragraph.

This line is also a separate paragraph, but... This line is only separated by a single newline, so it's a separate line in the same paragraph.