---
id: clockbook
title: Clockbook  Guide
sidebar_label: clockbook Guide
slug: /
---

---

## 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](https://stackoverflow.com/) 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.com), 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)

```js
[
    {
        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: boolean | If true, you'll get only archived clients. If false, you'll get only active clients |
| ----------------- | ----------------------------------------------------------------------------------- |
| _Still_           | `renders`                                                                           |
| 1                 | 2                                                                                   |

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)

```js

[
  {
    "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)

```js
{
"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

```js
{
"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)

```js
  {
"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`

```js
GET / workspaces / { workspaceId } / tags;
```

`REQUEST PARAMETERS`

| name: string in query             | If provided, tags will be filtered by name.                                         |
| --------------------------------- | ----------------------------------------------------------------------------------- |
| archived: boolean in query        | If true, you'll get only archived tags. <br/>If false, you'll get only active tags. |
| page: integer default: 1 in query | page                                                                                |

| page-size: integ
| is-active:boolean
er <br/> default: 50 in query | page-size |

`RESPONSES`

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 200 OK  <span style={{paddingLeft: "20px", fontWeight: 200}}> OK </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 401 Unauthorized
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Unauthorized </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>403 Forbidden <span style={{paddingLeft: "20px", fontWeight: 200}}> Forbidden </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>404 Not Found <span style={{paddingLeft: "20px", fontWeight: 200}}> Not Found  </span>   </p>

Response Content-Types: _/_

Response Example (200 OK)

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

---

### Add a new tag to workspace

Request Content-Types: application/json

Request Example

```js
{
"name": "Tag 1"
}
```

Response Content-Types: _/_

Response Example (201 Created)

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

### Update tag

`PATH`

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

`RESPONSES`

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 200 OK  <span style={{paddingLeft: "20px", fontWeight: 200}}> OK </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>201 Created
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Created </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 401 Unauthorized
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Unauthorized </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>403 Forbidden <span style={{paddingLeft: "20px", fontWeight: 200}}> Forbidden </span></p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>404 Not Found <span style={{paddingLeft: "20px", fontWeight: 200}}> Not Found  </span></p>

---

### Delete tag

`PATH`

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

`RESPONSES`

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 200 OK  <span style={{paddingLeft: "20px", fontWeight: 200}}> OK </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>204 No Content
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Content </span></p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>400 Bad Request
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Bad Request </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 401 Unauthorized
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Unauthorized </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>403 Forbidden <span style={{paddingLeft: "20px", fontWeight: 200}}> Forbidden </span></p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>404 Not Found <span style={{paddingLeft: "20px", fontWeight: 200}}> Not Found  </span></p>

---

## Task

Endpoints for manipulating TASK resource

Response Content-Types: _/_

Response Example (200 OK)

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

---

### Find tasks on project

---

`PATH`

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

`REQUEST PARAMETERS`

| is-active: boolean in query             | If provided and true, only active tasks will be returned. <br/> Otherwise only finished tasks will be returned. |
| --------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| name: string in query                   | If provided, tasks will be filtered by name.                                                                    |
| page: integer default: 1 in query       | page                                                                                                            |
| page-size: integer default: 50 in query | page-size                                                                                                       |

`RESPONSES`

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 200 OK  <span style={{paddingLeft: "20px", fontWeight: 200}}> OK </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 401 Unauthorized
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Unauthorized </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>403 Forbidden <span style={{paddingLeft: "20px", fontWeight: 200}}> Forbidden </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>404 Not Found <span style={{paddingLeft: "20px", fontWeight: 200}}> Not Found  </span>   </p>

---

### Find task on project by ID

---

`PATH`

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

`RESPONSES`

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 200 OK  <span style={{paddingLeft: "20px", fontWeight: 200}}> OK </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 401 Unauthorized
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Unauthorized </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>403 Forbidden <span style={{paddingLeft: "20px", fontWeight: 200}}> Forbidden </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>404 Not Found <span style={{paddingLeft: "20px", fontWeight: 200}}> Not Found  </span>   </p>

### Add a new task on project

`PATH`

```js
POST / workspaces / { workspaceId } / projects / { projectId } / tasks;
```

`RESPONSES`

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 200 OK  <span style={{paddingLeft: "20px", fontWeight: 200}}> OK </span>   </p>

---

<p style={{textAlign: "center",  textAlign: 'right',  fontWeight: 900, padding: "0px"}}> 400 Bad Request
 <span style={{paddingLeft: "25px",  fontWeight: 200}}> Task with that name already exists <br/> on project, or specified project <br/> doesn't exist </span> </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}> 401 Unauthorized
 <span style={{paddingLeft: "20px", fontWeight: 200}}> Unauthorized </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>403 Forbidden <span style={{paddingLeft: "20px", fontWeight: 200}}> Forbidden </span>   </p>

---

<p style={{textAlign: "center", fontWeight: 900, padding: "0px"}}>404 Not Found <span style={{paddingLeft: "20px", fontWeight: 200}}> Not Found  </span>   </p>

## 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)

```js
[
  {
    "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_.

---
