Time Records

Personas in this Story: Default, Member.

Lets see if we have time records in the target project

Response: HTTP 200, application/json (Hide)
GET /projects/1/time-records

Response:

1
2
3
4
{
    "time_records": null,
    "related": null
}

There are no time records tracked on this project yet. Before we can add new records, we need to see which job types are defined. We can get a list by requesting data from /job-types command:

Response: HTTP 200, application/json (Hide)
GET /job-types

Response:

1
2
3
4
5
6
7
8
9
10
11
12
[
    {
        "id": 1,
        "class": "JobType",
        "url_path": "\/job-types\/1",
        "name": "General",
        "is_archived": false,
        "updated_on": null,
        "is_default": true,
        "default_hourly_rate": 100
    }
]

Now that we know that we have a valid job type that we can use, lets add two time records, one attached directly to the project (we simply ommit task_id value) and one added to a task:

Response: HTTP 200, application/json (Hide)
POST /projects/1/time-records

Payload:

1
2
3
4
5
6
7
{
    "value": 1.5,
    "user_id": 1,
    "job_type_id": 1,
    "record_date": "2014-05-14",
    "billable_status": 0
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 1,
        "class": "TimeRecord",
        "url_path": "\/projects\/1\/time-records\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "billable_status": 0,
        "value": 1.5,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Project",
        "parent_id": 1,
        "created_on": 1430164445,
        "created_by_id": 1,
        "updated_on": 1430164445,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}
Response: HTTP 200, application/json (Hide)
GET /projects/1/tasks/1

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
    "single": {
        "id": 1,
        "class": "Task",
        "url_path": "\/projects\/1\/tasks\/1",
        "name": "Test Task #1",
        "assignee_id": 0,
        "delegated_by_id": 0,
        "completed_on": null,
        "completed_by_id": null,
        "is_completed": false,
        "comments_count": 0,
        "attachments": [],
        "labels": [],
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "project_id": 1,
        "is_hidden_from_clients": false,
        "body": "",
        "body_formatted": "",
        "created_on": 1430164444,
        "created_by_id": 1,
        "updated_on": 1430164444,
        "updated_by_id": 1,
        "task_number": 1,
        "task_list_id": 0,
        "position": 1,
        "is_important": false,
        "due_on": null,
        "estimate": 0,
        "job_type_id": 0,
        "total_subtasks": 0,
        "completed_subtasks": 0,
        "open_subtasks": 0
    },
    "subscribers": [
        1
    ],
    "comments": [],
    "reminders": [],
    "subtasks": [],
    "task_list": null,
    "tracked_time": 0,
    "tracked_expenses": 0
}
Response: HTTP 200, application/json (Hide)
POST /projects/1/time-records

Payload:

1
2
3
4
5
6
7
{
    "task_id": 1,
    "value": "2:30",
    "user_id": 1,
    "job_type_id": 1,
    "record_date": "2014-05-14"
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 2,
        "class": "TimeRecord",
        "url_path": "\/projects\/1\/time-records\/2",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "billable_status": 1,
        "value": 2.5,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Task",
        "parent_id": 1,
        "created_on": 1430164446,
        "created_by_id": 1,
        "updated_on": 1430164446,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}
Response: HTTP 200, application/json (Hide)
GET /projects/1/tasks/1

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
{
    "single": {
        "id": 1,
        "class": "Task",
        "url_path": "\/projects\/1\/tasks\/1",
        "name": "Test Task #1",
        "assignee_id": 0,
        "delegated_by_id": 0,
        "completed_on": null,
        "completed_by_id": null,
        "is_completed": false,
        "comments_count": 0,
        "attachments": [],
        "labels": [],
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "project_id": 1,
        "is_hidden_from_clients": false,
        "body": "",
        "body_formatted": "",
        "created_on": 1430164444,
        "created_by_id": 1,
        "updated_on": 1430164446,
        "updated_by_id": 1,
        "task_number": 1,
        "task_list_id": 0,
        "position": 1,
        "is_important": false,
        "due_on": null,
        "estimate": 0,
        "job_type_id": 0,
        "total_subtasks": 0,
        "completed_subtasks": 0,
        "open_subtasks": 0
    },
    "subscribers": [
        1
    ],
    "comments": [],
    "reminders": [],
    "subtasks": [],
    "task_list": null,
    "tracked_time": 2.5,
    "tracked_expenses": 0
}

Track time in the second project:

Response: HTTP 200, application/json (Hide)
POST /projects/2/time-records

Payload:

1
2
3
4
5
6
{
    "value": "3:30",
    "user_id": 1,
    "job_type_id": 1,
    "record_date": "2014-05-14"
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 3,
        "class": "TimeRecord",
        "url_path": "\/projects\/2\/time-records\/3",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "billable_status": 1,
        "value": 3.5,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Project",
        "parent_id": 2,
        "created_on": 1430164446,
        "created_by_id": 1,
        "updated_on": 1430164446,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}

Project's /time-records request should return all records that are tracked on that projects, including project's tasks:

Response: HTTP 200, application/json (Hide)
GET /projects/1/time-records

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
{
    "time_records": [
        {
            "id": 2,
            "class": "TimeRecord",
            "url_path": "\/projects\/1\/time-records\/2",
            "is_trashed": false,
            "trashed_on": null,
            "trashed_by_id": 0,
            "billable_status": 1,
            "value": 2.5,
            "record_date": 1400025600,
            "summary": null,
            "user_id": 1,
            "parent_type": "Task",
            "parent_id": 1,
            "created_on": 1430164446,
            "created_by_id": 1,
            "updated_on": 1430164446,
            "updated_by_id": 1,
            "job_type_id": 1
        },
        {
            "id": 1,
            "class": "TimeRecord",
            "url_path": "\/projects\/1\/time-records\/1",
            "is_trashed": false,
            "trashed_on": null,
            "trashed_by_id": 0,
            "billable_status": 0,
            "value": 1.5,
            "record_date": 1400025600,
            "summary": null,
            "user_id": 1,
            "parent_type": "Project",
            "parent_id": 1,
            "created_on": 1430164445,
            "created_by_id": 1,
            "updated_on": 1430164445,
            "updated_by_id": 1,
            "job_type_id": 1
        }
    ],
    "related": {
        "Project": {
            "1": {
                "id": 1,
                "class": "Project",
                "url_path": "\/projects\/1",
                "name": "First Project",
                "completed_on": null,
                "completed_by_id": null,
                "is_completed": false,
                "members": [
                    1,
                    2
                ],
                "category_id": 0,
                "label_id": 0,
                "is_trashed": false,
                "trashed_on": null,
                "trashed_by_id": 0,
                "created_on": 1430164444,
                "created_by_id": 1,
                "updated_on": 1430164446,
                "updated_by_id": 1,
                "body": null,
                "body_formatted": "",
                "company_id": 1,
                "leader_id": 1,
                "currency_id": 2,
                "template_id": 0,
                "based_on_type": null,
                "based_on_id": null,
                "email": "notifications+m2p-ttEJ9mi@mail.manageprojects.com",
                "is_tracking_enabled": true,
                "is_client_reporting_enabled": false,
                "budget": null,
                "count_tasks": 2,
                "count_discussions": 0,
                "count_files": 0,
                "count_notes": 0
            }
        },
        "Task": {
            "1": {
                "id": 1,
                "class": "Task",
                "url_path": "\/projects\/1\/tasks\/1",
                "name": "Test Task #1",
                "assignee_id": 0,
                "delegated_by_id": 0,
                "completed_on": null,
                "completed_by_id": null,
                "is_completed": false,
                "comments_count": 0,
                "attachments": [],
                "labels": [],
                "is_trashed": false,
                "trashed_on": null,
                "trashed_by_id": 0,
                "project_id": 1,
                "is_hidden_from_clients": false,
                "body": "",
                "body_formatted": "",
                "created_on": 1430164444,
                "created_by_id": 1,
                "updated_on": 1430164446,
                "updated_by_id": 1,
                "task_number": 1,
                "task_list_id": 0,
                "position": 1,
                "is_important": false,
                "due_on": null,
                "estimate": 0,
                "job_type_id": 0,
                "total_subtasks": 0,
                "completed_subtasks": 0,
                "open_subtasks": 0
            }
        }
    }
}

If we run the same request on task level, we should get only time records tracked for that task:

Response: HTTP 200, application/json (Hide)
GET /projects/1/tasks/1/time-records

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
{
    "time_records": [
        {
            "id": 2,
            "class": "TimeRecord",
            "url_path": "\/projects\/1\/time-records\/2",
            "is_trashed": false,
            "trashed_on": null,
            "trashed_by_id": 0,
            "billable_status": 1,
            "value": 2.5,
            "record_date": 1400025600,
            "summary": null,
            "user_id": 1,
            "parent_type": "Task",
            "parent_id": 1,
            "created_on": 1430164446,
            "created_by_id": 1,
            "updated_on": 1430164446,
            "updated_by_id": 1,
            "job_type_id": 1
        }
    ],
    "related": {
        "Project": {
            "1": {
                "id": 1,
                "class": "Project",
                "url_path": "\/projects\/1",
                "name": "First Project",
                "completed_on": null,
                "completed_by_id": null,
                "is_completed": false,
                "members": [
                    1,
                    2
                ],
                "category_id": 0,
                "label_id": 0,
                "is_trashed": false,
                "trashed_on": null,
                "trashed_by_id": 0,
                "created_on": 1430164444,
                "created_by_id": 1,
                "updated_on": 1430164446,
                "updated_by_id": 1,
                "body": null,
                "body_formatted": "",
                "company_id": 1,
                "leader_id": 1,
                "currency_id": 2,
                "template_id": 0,
                "based_on_type": null,
                "based_on_id": null,
                "email": "notifications+m2p-ttEJ9mi@mail.manageprojects.com",
                "is_tracking_enabled": true,
                "is_client_reporting_enabled": false,
                "budget": null,
                "count_tasks": 2,
                "count_discussions": 0,
                "count_files": 0,
                "count_notes": 0
            }
        },
        "Task": {
            "1": {
                "id": 1,
                "class": "Task",
                "url_path": "\/projects\/1\/tasks\/1",
                "name": "Test Task #1",
                "assignee_id": 0,
                "delegated_by_id": 0,
                "completed_on": null,
                "completed_by_id": null,
                "is_completed": false,
                "comments_count": 0,
                "attachments": [],
                "labels": [],
                "is_trashed": false,
                "trashed_on": null,
                "trashed_by_id": 0,
                "project_id": 1,
                "is_hidden_from_clients": false,
                "body": "",
                "body_formatted": "",
                "created_on": 1430164444,
                "created_by_id": 1,
                "updated_on": 1430164446,
                "updated_by_id": 1,
                "task_number": 1,
                "task_list_id": 0,
                "position": 1,
                "is_important": false,
                "due_on": null,
                "estimate": 0,
                "job_type_id": 0,
                "total_subtasks": 0,
                "completed_subtasks": 0,
                "open_subtasks": 0
            }
        }
    }
}

In order to alter this value, we can send PUT request:

Response: HTTP 200, application/json (Hide)
PUT /projects/1/time-records/1

Payload:

1
2
3
4
{
    "value": "3:15",
    "billable_status": 1
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 1,
        "class": "TimeRecord",
        "url_path": "\/projects\/1\/time-records\/1",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "billable_status": 1,
        "value": 3.25,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Project",
        "parent_id": 1,
        "created_on": 1430164445,
        "created_by_id": 1,
        "updated_on": 1430164446,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}

We just realized that task time record that we added is logged for the incorrect task. Note that sending PUT request with project_id or task_id will note move the record:

Response: HTTP 200, application/json (Hide)
PUT /projects/1/time-records/2

Payload:

1
2
3
4
{
    "project_id": 2,
    "task_id": 2
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 2,
        "class": "TimeRecord",
        "url_path": "\/projects\/1\/time-records\/2",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "billable_status": 1,
        "value": 2.5,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Task",
        "parent_id": 1,
        "created_on": 1430164446,
        "created_by_id": 1,
        "updated_on": 1430164447,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}

For move to work, we need to call /projects/:project_id/time-records/:time_record_id/move:

Response: HTTP 200, application/json (Hide)
PUT /projects/1/time-records/2/move

Payload:

1
2
3
{
    "task_id": 2
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 2,
        "class": "TimeRecord",
        "url_path": "\/projects\/1\/time-records\/2",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "billable_status": 1,
        "value": 2.5,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Task",
        "parent_id": 2,
        "created_on": 1430164446,
        "created_by_id": 1,
        "updated_on": 1430164447,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}

To move the time record on project level, send an empty value for task_id and project_id values:

Response: HTTP 200, application/json (Hide)
PUT /projects/1/time-records/2/move

Payload:

1
2
3
4
{
    "project_id": 2,
    "task_id": 0
}

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 2,
        "class": "TimeRecord",
        "url_path": "\/projects\/2\/time-records\/2",
        "is_trashed": false,
        "trashed_on": null,
        "trashed_by_id": 0,
        "billable_status": 1,
        "value": 2.5,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Project",
        "parent_id": 2,
        "created_on": 1430164446,
        "created_by_id": 1,
        "updated_on": 1430164447,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}

Finally, lets move the newly created time record to trash:

Response: HTTP 200, application/json (Hide)
DELETE /projects/1/time-records/1

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 1,
        "class": "TimeRecord",
        "url_path": "\/projects\/1\/time-records\/1",
        "is_trashed": true,
        "trashed_on": 1430164447,
        "trashed_by_id": 1,
        "billable_status": 1,
        "value": 3.25,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Project",
        "parent_id": 1,
        "created_on": 1430164445,
        "created_by_id": 1,
        "updated_on": 1430164447,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}

Confirmation that the record was deleted:

Response: HTTP 200, application/json (Hide)
GET /projects/1/time-records/1

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{
    "single": {
        "id": 1,
        "class": "TimeRecord",
        "url_path": "\/projects\/1\/time-records\/1",
        "is_trashed": true,
        "trashed_on": 1430164447,
        "trashed_by_id": 1,
        "billable_status": 1,
        "value": 3.25,
        "record_date": 1400025600,
        "summary": null,
        "user_id": 1,
        "parent_type": "Project",
        "parent_id": 1,
        "created_on": 1430164445,
        "created_by_id": 1,
        "updated_on": 1430164447,
        "updated_by_id": 1,
        "job_type_id": 1
    }
}

Lets check if user time records returns a proper list of records (cross-project):

Response: HTTP 200, application/json (Hide)
GET /users/1/time-records

Response:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
{
    "time_records": [
        {
            "id": 3,
            "class": "TimeRecord",
            "url_path": "\/projects\/2\/time-records\/3",
            "is_trashed": false,
            "trashed_on": null,
            "trashed_by_id": 0,
            "billable_status": 1,
            "value": 3.5,
            "record_date": 1400025600,
            "summary": null,
            "user_id": 1,
            "parent_type": "Project",
            "parent_id": 2,
            "created_on": 1430164446,
            "created_by_id": 1,
            "updated_on": 1430164446,
            "updated_by_id": 1,
            "job_type_id": 1
        },
        {
            "id": 2,
            "class": "TimeRecord",
            "url_path": "\/projects\/2\/time-records\/2",
            "is_trashed": false,
            "trashed_on": null,
            "trashed_by_id": 0,
            "billable_status": 1,
            "value": 2.5,
            "record_date": 1400025600,
            "summary": null,
            "user_id": 1,
            "parent_type": "Project",
            "parent_id": 2,
            "created_on": 1430164446,
            "created_by_id": 1,
            "updated_on": 1430164447,
            "updated_by_id": 1,
            "job_type_id": 1
        }
    ],
    "related": {
        "Project": {
            "2": {
                "id": 2,
                "class": "Project",
                "url_path": "\/projects\/2",
                "name": "Second Project",
                "completed_on": null,
                "completed_by_id": null,
                "is_completed": false,
                "members": [
                    1,
                    2
                ],
                "category_id": 0,
                "label_id": 0,
                "is_trashed": false,
                "trashed_on": null,
                "trashed_by_id": 0,
                "created_on": 1430164444,
                "created_by_id": 1,
                "updated_on": 1430164447,
                "updated_by_id": 1,
                "body": null,
                "body_formatted": "",
                "company_id": 1,
                "leader_id": 1,
                "currency_id": 2,
                "template_id": 0,
                "based_on_type": null,
                "based_on_id": null,
                "email": "notifications+m2p-tH3Ofwn@mail.manageprojects.com",
                "is_tracking_enabled": true,
                "is_client_reporting_enabled": false,
                "budget": null,
                "count_tasks": 0,
                "count_discussions": 0,
                "count_files": 0,
                "count_notes": 0
            }
        }
    }
}