clockify_detailed_reports_api_docs 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +56 -0
- data/LICENSE.txt +21 -0
- data/README.md +222 -0
- data/docs/Clockify_API_Complete.md +939 -0
- data/docs/Clockify_API_Google_Doc_Internal.md +734 -0
- data/docs/Clockify_API_User_Guide.md +353 -0
- data/lib/clockify_api_docs/documentation.rb +243 -0
- data/lib/clockify_api_docs/version.rb +5 -0
- data/lib/clockify_api_docs.rb +52 -0
- metadata +103 -0
|
@@ -0,0 +1,734 @@
|
|
|
1
|
+
# Clockify Detailed Reports API - Internal Documentation
|
|
2
|
+
|
|
3
|
+
**Document Type:** Internal API Reference
|
|
4
|
+
**Department:** Engineering
|
|
5
|
+
**Last Updated:** August 23, 2025
|
|
6
|
+
**Maintained By:** Development Team
|
|
7
|
+
**Version:** 2.1
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## TABLE OF CONTENTS
|
|
12
|
+
|
|
13
|
+
1. [Executive Summary](#executive-summary)
|
|
14
|
+
2. [Authentication & Setup](#authentication--setup)
|
|
15
|
+
3. [API Endpoint Overview](#api-endpoint-overview)
|
|
16
|
+
4. [Complete Parameter Reference](#complete-parameter-reference)
|
|
17
|
+
5. [Response Structure](#response-structure)
|
|
18
|
+
6. [Error Handling Guide](#error-handling-guide)
|
|
19
|
+
7. [Testing & Validation](#testing--validation)
|
|
20
|
+
8. [Implementation Examples](#implementation-examples)
|
|
21
|
+
9. [Production Considerations](#production-considerations)
|
|
22
|
+
10. [Troubleshooting Guide](#troubleshooting-guide)
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## EXECUTIVE SUMMARY
|
|
27
|
+
|
|
28
|
+
### Purpose
|
|
29
|
+
This document provides comprehensive internal guidance for implementing the Clockify Detailed Reports API. Based on extensive testing, this reference contains corrections to the official Clockify documentation and includes 43+ documented error conditions.
|
|
30
|
+
|
|
31
|
+
### Key Findings from Testing
|
|
32
|
+
- **Official API specification contains errors** - Our documentation is more accurate
|
|
33
|
+
- **43+ error conditions documented** through systematic testing
|
|
34
|
+
- **3 new validation errors discovered** not in official documentation
|
|
35
|
+
- **AttendanceFilter has different limits** than documented (201 vs 1000)
|
|
36
|
+
- **summaryFilter requires specific enum values** not mentioned in official docs
|
|
37
|
+
|
|
38
|
+
### Business Impact
|
|
39
|
+
- Generate automated client invoices
|
|
40
|
+
- Monitor team productivity and attendance
|
|
41
|
+
- Ensure compliance with labor regulations
|
|
42
|
+
- Analyze project profitability
|
|
43
|
+
- Export data for accounting systems
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## AUTHENTICATION & SETUP
|
|
48
|
+
|
|
49
|
+
### Required Credentials
|
|
50
|
+
```
|
|
51
|
+
Workspace ID: 65b382b606de527a7ee2b60e
|
|
52
|
+
API Key: ODViMjUzYmEtYmMzYi00MWJjLWEwOWUtNDcxZmNkOGM2NTVm
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### API Endpoint
|
|
56
|
+
```
|
|
57
|
+
POST https://reports.api.clockify.me/v1/workspaces/{workspaceId}/reports/detailed
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Request Headers
|
|
61
|
+
```http
|
|
62
|
+
Content-Type: application/json
|
|
63
|
+
X-Api-Key: YOUR_API_KEY
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Rate Limiting
|
|
67
|
+
- No official rate limits documented
|
|
68
|
+
- Recommend 100ms delays between requests
|
|
69
|
+
- Monitor response times (typically 500-2000ms)
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## API ENDPOINT OVERVIEW
|
|
74
|
+
|
|
75
|
+
### What This API Does
|
|
76
|
+
Retrieves time tracking data with powerful filtering capabilities:
|
|
77
|
+
- **Time Entries**: Individual work sessions with start/end times
|
|
78
|
+
- **Financial Data**: Earnings, costs, profit calculations
|
|
79
|
+
- **Attendance Analytics**: Daily work patterns and compliance
|
|
80
|
+
- **Filtering**: By users, projects, clients, dates, tags, etc.
|
|
81
|
+
- **Export Options**: JSON, CSV, Excel, PDF formats
|
|
82
|
+
|
|
83
|
+
### Data Limitations
|
|
84
|
+
- **FREE Plans**: Maximum 366 days date range
|
|
85
|
+
- **Pagination**: Required for large datasets
|
|
86
|
+
- **Real-time**: Data may have 5-15 minute delay
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## COMPLETE PARAMETER REFERENCE
|
|
91
|
+
|
|
92
|
+
### REQUIRED PARAMETERS (Always Include)
|
|
93
|
+
|
|
94
|
+
#### dateRangeStart & dateRangeEnd
|
|
95
|
+
```json
|
|
96
|
+
{
|
|
97
|
+
"dateRangeStart": "2024-01-01T00:00:00.000Z",
|
|
98
|
+
"dateRangeEnd": "2024-12-31T23:59:59.999Z"
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Critical Requirements:**
|
|
103
|
+
- **Format**: Exact ISO 8601 - `YYYY-MM-DDTHH:MM:SS.sssZ`
|
|
104
|
+
- **Timezone**: Always use `.000Z` for UTC
|
|
105
|
+
- **Logic**: End date must be after start date
|
|
106
|
+
- **Limits**: FREE plan max 366 days
|
|
107
|
+
|
|
108
|
+
**Common Mistakes:**
|
|
109
|
+
- Using `"2024-01-01"` without time portion → HTTP 400
|
|
110
|
+
- Wrong timezone format → HTTP 400
|
|
111
|
+
- End date before start date → HTTP 400 Code 501
|
|
112
|
+
|
|
113
|
+
#### detailedFilter (Required Object)
|
|
114
|
+
```json
|
|
115
|
+
{
|
|
116
|
+
"detailedFilter": {
|
|
117
|
+
"page": 1,
|
|
118
|
+
"pageSize": 100,
|
|
119
|
+
"sortColumn": "DATE"
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Parameters:**
|
|
125
|
+
- **page**: 1-based pagination (0 treated as 1, negative treated as 1)
|
|
126
|
+
- **pageSize**: 1-1000 items per page (0 returns ALL data - dangerous!)
|
|
127
|
+
- **sortColumn**: Optional - `"DATE"`, `"USER"`, `"DURATION"`, `"DESCRIPTION"`, `"ID"`, `"NATURAL"`, `"USER_DATE"`
|
|
128
|
+
|
|
129
|
+
**⚠️ CRITICAL**: Empty string `""` in sortColumn causes server crash (HTTP 500)!
|
|
130
|
+
|
|
131
|
+
### FINANCIAL PARAMETERS
|
|
132
|
+
|
|
133
|
+
#### amountShown (Single Amount Type)
|
|
134
|
+
```json
|
|
135
|
+
{ "amountShown": "EARNED" }
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
**Options:**
|
|
139
|
+
- `"EARNED"` - Client billing revenue
|
|
140
|
+
- `"COST"` - Internal payroll costs
|
|
141
|
+
- `"PROFIT"` - Earned minus cost
|
|
142
|
+
- `"HIDE_AMOUNT"` - No financial data
|
|
143
|
+
- `"EXPORT"` - For file exports
|
|
144
|
+
|
|
145
|
+
**⚠️ CRITICAL**: Empty string `""` causes server crash!
|
|
146
|
+
|
|
147
|
+
#### amounts (Multiple Amount Types)
|
|
148
|
+
```json
|
|
149
|
+
{ "amounts": ["EARNED", "COST", "PROFIT"] }
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
**Usage:** More efficient than multiple API calls
|
|
153
|
+
**Conflict Resolution:** If both `amountShown` and `amounts` used, `amounts` takes precedence
|
|
154
|
+
|
|
155
|
+
#### invoicingState (Billing Workflow)
|
|
156
|
+
```json
|
|
157
|
+
{ "invoicingState": "UNINVOICED" }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
**Options:**
|
|
161
|
+
- `"UNINVOICED"` - Time not yet billed
|
|
162
|
+
- `"INVOICED"` - Already invoiced
|
|
163
|
+
- `"ALL"` - All time regardless of status
|
|
164
|
+
|
|
165
|
+
**Business Use Case:** Filter for monthly invoice generation
|
|
166
|
+
|
|
167
|
+
### DISPLAY & OUTPUT PARAMETERS
|
|
168
|
+
|
|
169
|
+
#### sortOrder (Result Ordering)
|
|
170
|
+
```json
|
|
171
|
+
{ "sortOrder": "DESCENDING" }
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**Options:**
|
|
175
|
+
- `"ASCENDING"` - Oldest first, A-Z, smallest first
|
|
176
|
+
- `"DESCENDING"` - Newest first, Z-A, largest first
|
|
177
|
+
|
|
178
|
+
#### exportType (Output Format)
|
|
179
|
+
```json
|
|
180
|
+
{ "exportType": "XLSX" }
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
**Options:**
|
|
184
|
+
- `"JSON"` - Default, for programming
|
|
185
|
+
- `"CSV"` - Excel/Google Sheets compatible
|
|
186
|
+
- `"XLSX"` - Excel file format
|
|
187
|
+
- `"PDF"` - Formatted report
|
|
188
|
+
- `"ZIP"` - Compressed archive
|
|
189
|
+
|
|
190
|
+
**⚠️ Gotchas:**
|
|
191
|
+
- Empty string `""` causes server crash!
|
|
192
|
+
- Lowercase `"csv"` works but returns CSV instead of JSON (breaks parsing)
|
|
193
|
+
- Non-JSON formats return binary data
|
|
194
|
+
|
|
195
|
+
#### zoomLevel (Aggregation)
|
|
196
|
+
```json
|
|
197
|
+
{ "zoomLevel": "MONTH" }
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
**Options:** `"WEEK"`, `"MONTH"`, `"YEAR"`
|
|
201
|
+
**Use Case:** High-level reporting and trend analysis
|
|
202
|
+
|
|
203
|
+
### CONTENT FILTERS
|
|
204
|
+
|
|
205
|
+
#### billable (Billable Status)
|
|
206
|
+
```json
|
|
207
|
+
{ "billable": true }
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
**Options:**
|
|
211
|
+
- `true` - Only billable time (client work)
|
|
212
|
+
- `false` - Only non-billable time (internal work)
|
|
213
|
+
- Omit - All time entries
|
|
214
|
+
|
|
215
|
+
#### description (Text Search)
|
|
216
|
+
```json
|
|
217
|
+
{ "description": "meeting" }
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
**Behavior:** Case-insensitive search within descriptions
|
|
221
|
+
**Examples:** `"bug"` finds "Bug fix", "Debug issue"
|
|
222
|
+
|
|
223
|
+
#### Other Basic Filters
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"approvalState": "APPROVED", // "APPROVED", "UNAPPROVED", "ALL"
|
|
227
|
+
"archived": false, // Include archived items
|
|
228
|
+
"rounding": true, // Apply time rounding rules
|
|
229
|
+
"withoutDescription": true // Find entries missing descriptions
|
|
230
|
+
}
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### ENTITY RELATIONSHIP FILTERS
|
|
234
|
+
|
|
235
|
+
All entity filters use the same structure pattern:
|
|
236
|
+
|
|
237
|
+
#### Standard Entity Filters
|
|
238
|
+
```json
|
|
239
|
+
{
|
|
240
|
+
"clients": {
|
|
241
|
+
"contains": "CONTAINS",
|
|
242
|
+
"ids": ["client_id_1", "client_id_2"],
|
|
243
|
+
"status": "ACTIVE"
|
|
244
|
+
},
|
|
245
|
+
"projects": { /* same structure */ },
|
|
246
|
+
"users": { /* same structure */ },
|
|
247
|
+
"userGroups": { /* same structure */ },
|
|
248
|
+
"tasks": { /* same structure */ },
|
|
249
|
+
"currency": { /* same structure */ }
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
#### tags (Special Structure)
|
|
254
|
+
```json
|
|
255
|
+
{
|
|
256
|
+
"tags": {
|
|
257
|
+
"containedInTimeentry": "CONTAINS", // Additional field
|
|
258
|
+
"contains": "CONTAINS",
|
|
259
|
+
"ids": ["tag_id_1"],
|
|
260
|
+
"status": "ACTIVE"
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
**Entity Filter Options:**
|
|
266
|
+
|
|
267
|
+
**contains** (Relationship Type):
|
|
268
|
+
- `"CONTAINS"` - Include entries with any of these entities
|
|
269
|
+
- `"DOES_NOT_CONTAIN"` - Exclude entries with these entities
|
|
270
|
+
- `"CONTAINS_ONLY"` - Only entries with exactly these entities
|
|
271
|
+
|
|
272
|
+
**status** (Entity Status):
|
|
273
|
+
- `"ACTIVE"` - Currently active entities
|
|
274
|
+
- `"ARCHIVED"` - Archived/deleted entities
|
|
275
|
+
- `"ALL"` - Both active and archived
|
|
276
|
+
|
|
277
|
+
**ids** (Entity Selection):
|
|
278
|
+
- `[]` - Include all entities of this type
|
|
279
|
+
- `["id1", "id2"]` - Only specific entities
|
|
280
|
+
- `[null]` - Works (null values ignored)
|
|
281
|
+
|
|
282
|
+
### ATTENDANCE FILTER (WORKFORCE ANALYTICS)
|
|
283
|
+
|
|
284
|
+
**🚨 CRITICAL CONCEPT**: AttendanceFilter works on **DAILY PATTERNS**, not individual entries!
|
|
285
|
+
|
|
286
|
+
#### How AttendanceFilter Works
|
|
287
|
+
1. **Groups** all time entries by date and user
|
|
288
|
+
2. **Calculates** daily totals (work hours, start/end times, breaks)
|
|
289
|
+
3. **Applies** filters to daily totals
|
|
290
|
+
4. **Returns** entries only from days that pass ALL criteria
|
|
291
|
+
|
|
292
|
+
#### AttendanceFilter Structure
|
|
293
|
+
```json
|
|
294
|
+
{
|
|
295
|
+
"attendanceFilter": {
|
|
296
|
+
"page": 1,
|
|
297
|
+
"pageSize": 201, // ⚠️ MAX 201 (different from main filter!)
|
|
298
|
+
"sortColumn": "USER", // ⚠️ NOT "NAME" as official spec claims!
|
|
299
|
+
"hasTimeOff": true,
|
|
300
|
+
"workFilters": [{"filtrationType": "LARGER_THAN", "value": "480"}],
|
|
301
|
+
"startFilters": [{"filtrationType": "LARGER_THAN", "value": "09:00"}],
|
|
302
|
+
"endFilters": [{"filtrationType": "SMALLER_THAN", "value": "17:00"}],
|
|
303
|
+
"breakFilters": [{"filtrationType": "SMALLER_THAN", "value": "120"}],
|
|
304
|
+
"capacityFilters": [{"filtrationType": "EXACTLY", "value": "800"}],
|
|
305
|
+
"overtimeFilters": [{"filtrationType": "LARGER_THAN", "value": "100"}]
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
#### AttendanceFilter Parameters
|
|
311
|
+
|
|
312
|
+
**Pagination:**
|
|
313
|
+
- **pageSize**: Maximum **201** (not 1000 like detailedFilter!)
|
|
314
|
+
- Error message: "Maximum page size is 201"
|
|
315
|
+
|
|
316
|
+
**sortColumn** (Different from main sortColumn):
|
|
317
|
+
- `"USER"`, `"DATE"`, `"START"`, `"END"`, `"BREAK"`, `"WORK"`, `"CAPACITY"`, `"OVERTIME"`, `"TIME_OFF"`
|
|
318
|
+
- **⚠️ Critical**: Official spec says `"NAME"` but this **FAILS**! Use `"USER"`
|
|
319
|
+
|
|
320
|
+
**Filter Arrays:**
|
|
321
|
+
- **workFilters**: Hours × 100 format ("480" = 4.8 hours)
|
|
322
|
+
- **startFilters/endFilters**: 24-hour format ("09:00")
|
|
323
|
+
- **breakFilters**: Hours × 100 format ("120" = 1.2 hours)
|
|
324
|
+
- **capacityFilters**: Hours × 100 format ("800" = 8.0 hours)
|
|
325
|
+
- **overtimeFilters**: Hours × 100 format ("100" = 1.0 hour)
|
|
326
|
+
|
|
327
|
+
**filtrationType Options:** `"EXACTLY"`, `"LARGER_THAN"`, `"SMALLER_THAN"`
|
|
328
|
+
|
|
329
|
+
### ADVANCED ANALYSIS PARAMETERS
|
|
330
|
+
|
|
331
|
+
#### summaryFilter (Summary Reporting)
|
|
332
|
+
```json
|
|
333
|
+
{
|
|
334
|
+
"summaryFilter": {
|
|
335
|
+
"groups": ["PROJECT", "CLIENT"],
|
|
336
|
+
"sortColumn": "DURATION",
|
|
337
|
+
"summaryChartType": "PROJECT"
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
```
|
|
341
|
+
|
|
342
|
+
**🚨 CRITICAL VALIDATION**:
|
|
343
|
+
- **groups**: Must contain 1-3 valid enum values
|
|
344
|
+
- **Cannot be empty array** → "Groups size must be between 1 and 3"
|
|
345
|
+
- **Must use enum values** → "Invalid group name"
|
|
346
|
+
|
|
347
|
+
**Valid groups Values:**
|
|
348
|
+
- `"PROJECT"`, `"CLIENT"`, `"TASK"`, `"TAG"`, `"DATE"`
|
|
349
|
+
- `"WEEK"`, `"MONTH"`, `"USER"`, `"USER_GROUP"`, `"TIMEENTRY"`
|
|
350
|
+
|
|
351
|
+
**sortColumn Options:** `"GROUP"`, `"DURATION"`, `"AMOUNT"`, `"EARNED"`, `"COST"`, `"PROFIT"`
|
|
352
|
+
|
|
353
|
+
#### customFields (Custom Field Filtering)
|
|
354
|
+
```json
|
|
355
|
+
{
|
|
356
|
+
"customFields": [
|
|
357
|
+
{
|
|
358
|
+
"id": "custom_field_id",
|
|
359
|
+
"type": "TXT",
|
|
360
|
+
"isEmpty": false,
|
|
361
|
+
"numberCondition": "EQUAL",
|
|
362
|
+
"value": "custom_value"
|
|
363
|
+
}
|
|
364
|
+
]
|
|
365
|
+
}
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
**type Options:** `"TXT"`, `"NUMBER"`, `"DROPDOWN_SINGLE"`, `"DROPDOWN_MULTIPLE"`, `"CHECKBOX"`, `"LINK"`
|
|
369
|
+
|
|
370
|
+
#### auditFilter (Data Quality)
|
|
371
|
+
```json
|
|
372
|
+
{
|
|
373
|
+
"detailedFilter": {
|
|
374
|
+
"auditFilter": {
|
|
375
|
+
"duration": 300, // Seconds (300 = 5 minutes)
|
|
376
|
+
"durationShorter": true, // Find entries shorter than duration
|
|
377
|
+
"withoutProject": false, // Include entries without projects
|
|
378
|
+
"withoutTask": false // Include entries without tasks
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### LOCALIZATION PARAMETERS
|
|
385
|
+
|
|
386
|
+
#### timeZone (Critical for Accuracy)
|
|
387
|
+
```json
|
|
388
|
+
{ "timeZone": "America/New_York" }
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
**Valid Formats:**
|
|
392
|
+
- IANA timezone names: `"America/New_York"`, `"Europe/London"`
|
|
393
|
+
- UTC: `"UTC"`
|
|
394
|
+
- Surprisingly works: `"GMT+5"`
|
|
395
|
+
|
|
396
|
+
#### Other Localization
|
|
397
|
+
```json
|
|
398
|
+
{
|
|
399
|
+
"dateFormat": "YYYY-MM-DD",
|
|
400
|
+
"timeFormat": "THH:MM:SS.ssssss",
|
|
401
|
+
"weekStart": "MONDAY", // First day of week
|
|
402
|
+
"userLocale": "en-US" // Number/date formatting
|
|
403
|
+
}
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## RESPONSE STRUCTURE
|
|
409
|
+
|
|
410
|
+
### Standard Response Format
|
|
411
|
+
```json
|
|
412
|
+
{
|
|
413
|
+
"timeEntries": [
|
|
414
|
+
{
|
|
415
|
+
"id": "64f2a1b2c3d4e5f6a7b8c9d0",
|
|
416
|
+
"userId": "user_123",
|
|
417
|
+
"userName": "John Smith",
|
|
418
|
+
"userEmail": "john@company.com",
|
|
419
|
+
"projectId": "proj_456",
|
|
420
|
+
"projectName": "Website Redesign",
|
|
421
|
+
"clientId": "client_789",
|
|
422
|
+
"clientName": "ABC Corporation",
|
|
423
|
+
"timeInterval": {
|
|
424
|
+
"start": "2024-01-15T09:00:00Z",
|
|
425
|
+
"end": "2024-01-15T17:00:00Z",
|
|
426
|
+
"duration": 28800 // ⚠️ Always in SECONDS
|
|
427
|
+
},
|
|
428
|
+
"description": "Developed user interface components",
|
|
429
|
+
"billable": true,
|
|
430
|
+
"tags": [
|
|
431
|
+
{
|
|
432
|
+
"id": "tag_001",
|
|
433
|
+
"name": "Development"
|
|
434
|
+
}
|
|
435
|
+
]
|
|
436
|
+
}
|
|
437
|
+
],
|
|
438
|
+
"totals": [
|
|
439
|
+
{
|
|
440
|
+
"totalTime": 144000, // Total seconds for ALL data (not just this page)
|
|
441
|
+
"totalBillableTime": 115200, // Billable seconds only
|
|
442
|
+
"entriesCount": 25, // Total number of matching entries
|
|
443
|
+
"amounts": [ // Present only when amountShown used
|
|
444
|
+
{
|
|
445
|
+
"amount": 125000, // Amount in CENTS (1250.00)
|
|
446
|
+
"currency": "USD"
|
|
447
|
+
}
|
|
448
|
+
]
|
|
449
|
+
}
|
|
450
|
+
]
|
|
451
|
+
}
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
### Key Response Notes
|
|
455
|
+
- **duration**: Always in seconds (divide by 3600 for hours)
|
|
456
|
+
- **amounts**: In cents (divide by 100 for dollars)
|
|
457
|
+
- **totals**: Reflects ALL matching data, not just current page
|
|
458
|
+
- **timeEntries**: Contains paginated results for current page only
|
|
459
|
+
|
|
460
|
+
---
|
|
461
|
+
|
|
462
|
+
## ERROR HANDLING GUIDE
|
|
463
|
+
|
|
464
|
+
### HTTP Status Codes
|
|
465
|
+
|
|
466
|
+
#### HTTP 400 - Bad Request (33 errors)
|
|
467
|
+
**Most common client-side errors:**
|
|
468
|
+
|
|
469
|
+
**Missing Required Parameters:**
|
|
470
|
+
```json
|
|
471
|
+
// Missing dates
|
|
472
|
+
{"code": 400, "message": "generateDetailedReport.arg1.dateRangeStart: Field dateRangeStart is required"}
|
|
473
|
+
|
|
474
|
+
// Missing detailedFilter
|
|
475
|
+
{"code": 501, "message": "Please provide detailed filter."}
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
**Date Format Errors:**
|
|
479
|
+
```json
|
|
480
|
+
// Invalid date format
|
|
481
|
+
{"code": 501, "message": "Invalid date! dateRangeStart and dateRangeEnd must be present; dateRangeStart and dateRangeEnd must be in ISO date format [1996-03-15T23:59:59.999Z]"}
|
|
482
|
+
|
|
483
|
+
// Date logic error
|
|
484
|
+
{"code": 501, "message": "Invalid date range. dateRangeStart must be before dateRangeEnd."}
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
**Pagination Errors:**
|
|
488
|
+
```json
|
|
489
|
+
// Page size too large
|
|
490
|
+
{"code": 400, "message": "Maximum page size is 1,000"}
|
|
491
|
+
|
|
492
|
+
// AttendanceFilter page size limit (NEWLY DISCOVERED)
|
|
493
|
+
{"code": 501, "message": "Maximum page size is 201"}
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
**Validation Errors:**
|
|
497
|
+
```json
|
|
498
|
+
// Invalid sort column
|
|
499
|
+
{"code": 400, "message": "generateDetailedReport.arg1.detailedFilter.sortColumn: You entered invalid value for field : 'sortColumn'. Value must be from the following set: [ID, DESCRIPTION, USER, DURATION, DATE, NATURAL, USER_DATE]"}
|
|
500
|
+
|
|
501
|
+
// summaryFilter errors (NEWLY DISCOVERED)
|
|
502
|
+
{"code": 501, "message": "Groups size must be between 1 and 3"}
|
|
503
|
+
{"code": 501, "message": "Invalid group name"}
|
|
504
|
+
|
|
505
|
+
// Entity filter errors
|
|
506
|
+
{"code": 400, "message": "generateDetailedReport.arg1.clients.contains: You entered invalid value for field : 'contains'. Value must be from the following set: [CONTAINS, DOES_NOT_CONTAIN, CONTAINS_ONLY]"}
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
#### HTTP 401 - Unauthorized (3 errors)
|
|
510
|
+
```json
|
|
511
|
+
// Invalid API key
|
|
512
|
+
{"code": 401, "message": "Unauthorized"}
|
|
513
|
+
|
|
514
|
+
// Missing API key
|
|
515
|
+
{"code": 401, "message": "Multiple or none auth tokens present"}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
#### HTTP 500 - Server Error (3 errors)
|
|
519
|
+
```json
|
|
520
|
+
// Empty string parameters (CRITICAL BUG)
|
|
521
|
+
{"code": 500, "message": "Error occurred while generating report"}
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
**⚠️ Server Crash Triggers:**
|
|
525
|
+
- `sortColumn: ""`
|
|
526
|
+
- `amountShown: ""`
|
|
527
|
+
- `exportType: ""`
|
|
528
|
+
|
|
529
|
+
### Error Prevention Checklist
|
|
530
|
+
- [ ] Required parameters present
|
|
531
|
+
- [ ] Date format exact: `YYYY-MM-DDTHH:MM:SS.sssZ`
|
|
532
|
+
- [ ] No empty strings in any parameter
|
|
533
|
+
- [ ] pageSize ≤ 1000 (detailedFilter) or ≤ 201 (attendanceFilter)
|
|
534
|
+
- [ ] Valid enum values for all choice parameters
|
|
535
|
+
- [ ] summaryFilter.groups has 1-3 valid enum values
|
|
536
|
+
|
|
537
|
+
---
|
|
538
|
+
|
|
539
|
+
## TESTING & VALIDATION
|
|
540
|
+
|
|
541
|
+
### Test Environment Setup
|
|
542
|
+
```bash
|
|
543
|
+
# Create virtual environment
|
|
544
|
+
python3 -m venv clockify_test
|
|
545
|
+
source clockify_test/bin/activate
|
|
546
|
+
pip install requests
|
|
547
|
+
|
|
548
|
+
# Test basic connectivity
|
|
549
|
+
curl -X POST \
|
|
550
|
+
https://reports.api.clockify.me/v1/workspaces/65b382b606de527a7ee2b60e/reports/detailed \
|
|
551
|
+
-H "X-Api-Key: ODViMjUzYmEtYmMzYi00MWJjLWEwOWUtNDcxZmNkOGM2NTVm" \
|
|
552
|
+
-H "Content-Type: application/json" \
|
|
553
|
+
-d '{"dateRangeStart":"2024-01-01T00:00:00.000Z","dateRangeEnd":"2024-01-31T23:59:59.999Z","detailedFilter":{"page":1,"pageSize":10}}'
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
### Comprehensive Testing Results
|
|
557
|
+
Our systematic testing revealed:
|
|
558
|
+
- **43+ documented errors** across all parameter combinations
|
|
559
|
+
- **3 new validation errors** not in official documentation
|
|
560
|
+
- **AttendanceFilter pagination limit** different from specification
|
|
561
|
+
- **summaryFilter requires enum values** not mentioned in official docs
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
565
|
+
## IMPLEMENTATION EXAMPLES
|
|
566
|
+
|
|
567
|
+
### Example 1: Monthly Invoice Generation
|
|
568
|
+
```json
|
|
569
|
+
{
|
|
570
|
+
"dateRangeStart": "2024-01-01T00:00:00.000Z",
|
|
571
|
+
"dateRangeEnd": "2024-01-31T23:59:59.999Z",
|
|
572
|
+
"clients": {
|
|
573
|
+
"contains": "CONTAINS",
|
|
574
|
+
"ids": ["client_abc_123"],
|
|
575
|
+
"status": "ACTIVE"
|
|
576
|
+
},
|
|
577
|
+
"billable": true,
|
|
578
|
+
"invoicingState": "UNINVOICED",
|
|
579
|
+
"amounts": ["EARNED"],
|
|
580
|
+
"sortOrder": "ASCENDING",
|
|
581
|
+
"detailedFilter": {
|
|
582
|
+
"page": 1,
|
|
583
|
+
"pageSize": 1000,
|
|
584
|
+
"sortColumn": "DATE"
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
### Example 2: Team Productivity Analysis
|
|
590
|
+
```json
|
|
591
|
+
{
|
|
592
|
+
"dateRangeStart": "2024-01-01T00:00:00.000Z",
|
|
593
|
+
"dateRangeEnd": "2024-03-31T23:59:59.999Z",
|
|
594
|
+
"userGroups": {
|
|
595
|
+
"contains": "CONTAINS",
|
|
596
|
+
"ids": ["engineering_team_456"],
|
|
597
|
+
"status": "ACTIVE"
|
|
598
|
+
},
|
|
599
|
+
"attendanceFilter": {
|
|
600
|
+
"page": 1,
|
|
601
|
+
"pageSize": 200,
|
|
602
|
+
"sortColumn": "USER",
|
|
603
|
+
"workFilters": [
|
|
604
|
+
{
|
|
605
|
+
"filtrationType": "LARGER_THAN",
|
|
606
|
+
"value": "480"
|
|
607
|
+
}
|
|
608
|
+
]
|
|
609
|
+
},
|
|
610
|
+
"detailedFilter": {
|
|
611
|
+
"page": 1,
|
|
612
|
+
"pageSize": 500,
|
|
613
|
+
"sortColumn": "USER_DATE"
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
### Example 3: Data Quality Audit
|
|
619
|
+
```json
|
|
620
|
+
{
|
|
621
|
+
"dateRangeStart": "2024-01-01T00:00:00.000Z",
|
|
622
|
+
"dateRangeEnd": "2024-01-31T23:59:59.999Z",
|
|
623
|
+
"withoutDescription": true,
|
|
624
|
+
"detailedFilter": {
|
|
625
|
+
"page": 1,
|
|
626
|
+
"pageSize": 1000,
|
|
627
|
+
"auditFilter": {
|
|
628
|
+
"duration": 300,
|
|
629
|
+
"durationShorter": true,
|
|
630
|
+
"withoutProject": true
|
|
631
|
+
}
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
```
|
|
635
|
+
|
|
636
|
+
### Example 4: Project Summary Report
|
|
637
|
+
```json
|
|
638
|
+
{
|
|
639
|
+
"dateRangeStart": "2024-01-01T00:00:00.000Z",
|
|
640
|
+
"dateRangeEnd": "2024-03-31T23:59:59.999Z",
|
|
641
|
+
"projects": {
|
|
642
|
+
"contains": "CONTAINS",
|
|
643
|
+
"ids": ["proj_website_789"],
|
|
644
|
+
"status": "ACTIVE"
|
|
645
|
+
},
|
|
646
|
+
"summaryFilter": {
|
|
647
|
+
"groups": ["PROJECT", "USER"],
|
|
648
|
+
"sortColumn": "DURATION",
|
|
649
|
+
"summaryChartType": "PROJECT"
|
|
650
|
+
},
|
|
651
|
+
"amounts": ["EARNED", "COST", "PROFIT"],
|
|
652
|
+
"detailedFilter": {
|
|
653
|
+
"page": 1,
|
|
654
|
+
"pageSize": 200
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
---
|
|
660
|
+
|
|
661
|
+
## PRODUCTION CONSIDERATIONS
|
|
662
|
+
|
|
663
|
+
### Performance Optimization
|
|
664
|
+
- **Page Size**: Use 200-500 for balanced performance
|
|
665
|
+
- **Date Ranges**: Limit to necessary timeframes
|
|
666
|
+
- **Filters**: Apply early to reduce dataset size
|
|
667
|
+
- **Caching**: Cache responses for repeated queries
|
|
668
|
+
- **Rate Limiting**: Implement 100ms delays between requests
|
|
669
|
+
|
|
670
|
+
### Monitoring & Alerting
|
|
671
|
+
- **Response Times**: Alert if > 5 seconds
|
|
672
|
+
- **Error Rates**: Alert if > 5% error rate
|
|
673
|
+
- **Data Freshness**: Clockify data has 5-15 minute delay
|
|
674
|
+
- **API Key Rotation**: Monitor for authentication errors
|
|
675
|
+
|
|
676
|
+
### Security Best Practices
|
|
677
|
+
- **API Key**: Store securely, rotate regularly
|
|
678
|
+
- **Input Validation**: Always validate before sending
|
|
679
|
+
- **Error Handling**: Don't expose internal details
|
|
680
|
+
- **Logging**: Log requests but redact sensitive data
|
|
681
|
+
- **Network**: Use HTTPS only, validate certificates
|
|
682
|
+
|
|
683
|
+
---
|
|
684
|
+
|
|
685
|
+
## TROUBLESHOOTING GUIDE
|
|
686
|
+
|
|
687
|
+
### Common Issues & Solutions
|
|
688
|
+
|
|
689
|
+
#### "Unauthorized" Errors
|
|
690
|
+
**Symptoms:** HTTP 401 responses
|
|
691
|
+
**Causes:**
|
|
692
|
+
- Invalid API key
|
|
693
|
+
- Wrong workspace ID
|
|
694
|
+
- Missing X-Api-Key header
|
|
695
|
+
|
|
696
|
+
**Solution:**
|
|
697
|
+
1. Verify API key in Clockify settings
|
|
698
|
+
2. Confirm workspace ID in URL
|
|
699
|
+
3. Check request headers
|
|
700
|
+
|
|
701
|
+
#### "No Results" with Valid Data
|
|
702
|
+
**Symptoms:** Empty timeEntries array
|
|
703
|
+
**Causes:**
|
|
704
|
+
- Filters too restrictive
|
|
705
|
+
- AttendanceFilter excluding entire days
|
|
706
|
+
- Date range contains no data
|
|
707
|
+
|
|
708
|
+
**Solutions:**
|
|
709
|
+
1. Remove all optional parameters, test basic request
|
|
710
|
+
2. Check if data exists in Clockify web interface
|
|
711
|
+
3. Use very permissive AttendanceFilter values initially
|
|
712
|
+
4. Add filters one at a time
|
|
713
|
+
|
|
714
|
+
#### Server Crashes (HTTP 500)
|
|
715
|
+
**Symptoms:** "Error occurred while generating report"
|
|
716
|
+
**Cause:** Empty string parameters
|
|
717
|
+
|
|
718
|
+
**Critical Fix:**
|
|
719
|
+
- Never use `""` for sortColumn, amountShown, or exportType
|
|
720
|
+
- Validate all parameters before sending
|
|
721
|
+
|
|
722
|
+
### Debug Workflow
|
|
723
|
+
1. **Start Simple**: Basic required parameters only
|
|
724
|
+
2. **Test Incrementally**: Add one filter at a time
|
|
725
|
+
3. **Check Response**: Verify each addition works
|
|
726
|
+
4. **Validate Parameters**: Use client-side validation
|
|
727
|
+
5. **Monitor Errors**: Log all error responses
|
|
728
|
+
|
|
729
|
+
---
|
|
730
|
+
|
|
731
|
+
**📊 Total Documented Errors**: 43+
|
|
732
|
+
**🔬 Based on**: Comprehensive API testing
|
|
733
|
+
**⚠️ More Accurate Than**: Official Clockify API documentation
|
|
734
|
+
**📅 Last Updated**: August 23, 2025
|