#
tokens: 38740/50000 7/50 files (page 2/2)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 2 of 2. Use http://codebase.md/adrian-dotco/harvest-mcp-server?lines=true&page={x} to view the full context.

# Directory Structure

```
├── .github
│   └── workflows
│       ├── claude-code-review.yml
│       └── claude.yml
├── .gitignore
├── docs
│   └── harvest_api_docs
│       ├── 01_introduction
│       │   ├── 01_overview.md
│       │   ├── 02_postman_collection.md
│       │   ├── 03_code_samples.md
│       │   ├── 04_supported_timezones.md
│       │   ├── 05_supported_currencies.md
│       │   ├── 06_pagination.md
│       │   └── README.md
│       ├── 02_authentication
│       │   ├── 01_authentication.md
│       │   └── README.md
│       ├── 03_clients_api
│       │   ├── 01_clients.md
│       │   ├── 02_client_contacts.md
│       │   └── README.md
│       ├── 04_company
│       │   ├── 01_company.md
│       │   └── README.md
│       ├── 05_invoices
│       │   ├── 01_invoice_item_categories.md
│       │   ├── 02_invoice_messages.md
│       │   ├── 03_invoice_payments.md
│       │   ├── 04_invoices.md
│       │   └── README.md
│       ├── 06_estimates
│       │   ├── 01_estimate_item_categories.md
│       │   ├── 02_estimate_messages.md
│       │   ├── 03_estimates.md
│       │   └── README.md
│       ├── 07_expenses
│       │   ├── expense_categories.md
│       │   └── expenses.md
│       ├── 08_tasks
│       │   └── tasks.md
│       ├── 09_timesheets
│       │   └── time_entries.md
│       ├── 10_projects
│       │   ├── project_task_assignments.md
│       │   ├── project_user_assignments.md
│       │   └── projects.md
│       ├── 11_roles
│       │   └── roles.md
│       ├── 12_users
│       │   ├── billable_rates.md
│       │   ├── cost_rates.md
│       │   ├── project_assignments.md
│       │   ├── teammates.md
│       │   └── users.md
│       ├── 13_reports
│       │   ├── expenses.md
│       │   ├── project_budget.md
│       │   ├── time.md
│       │   └── uninvoiced.md
│       └── README.md
├── LICENSE
├── llms-install.md
├── package-lock.json
├── package.json
├── README.md
├── src
│   ├── index.ts
│   ├── setup.ts
│   └── types
│       └── chrono-node.d.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/docs/harvest_api_docs/07_expenses/expenses.md:
--------------------------------------------------------------------------------

```markdown
  1 | Expenses
  2 | 
  3 | The expense object⚭
  4 | 
  5 | Attribute Type  Description
  6 | id  integer Unique ID for the expense.
  7 | client  object  An object containing the expense’s client id, name, and currency.
  8 | project object  An object containing the expense’s project id, name, and code.
  9 | expense_category  object  An object containing the expense’s expense category id, name, unit_price, and unit_name.
 10 | user  object  An object containing the id and name of the user that recorded the expense.
 11 | user_assignment object  A user assignment object of the user that recorded the expense.
 12 | receipt object  An object containing the expense’s receipt URL and file name.
 13 | invoice object  Once the expense has been invoiced, this field will include the associated invoice’s id and number.
 14 | notes string  Textual notes used to describe the expense.
 15 | units integer The quantity of units used to calculate the total_cost of the expense.
 16 | total_cost  decimal The total amount of the expense.
 17 | billable  boolean Whether the expense is billable or not.
 18 | is_closed boolean Whether the expense has been approved or not.
 19 | is_locked boolean Whether the expense has been been invoiced, approved, or the project or person related to the expense is archived.
 20 | is_billed boolean Whether or not the expense has been marked as invoiced.
 21 | locked_reason string  An explanation of why the expense has been locked.
 22 | spent_date  date  Date the expense occurred.
 23 | created_at  datetime  Date and time the expense was created.
 24 | updated_at  datetime  Date and time the expense was last updated.
 25 | List all expenses⚭
 26 | 
 27 | Returns a list of your expenses. If accessing this endpoint as an Administrator, all expenses in the account will be returned. If accessing this endpoint as a Manager, all expenses for assigned teammates and managed projects will be returned. The expenses are returned sorted by the spent_at date, with the most recent expenses appearing first.
 28 | 
 29 | The response contains an object with a expenses property that contains an array of up to per_page expenses. Each entry in the array is a separate expense object. If no more expenses are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your expenses.
 30 | 
 31 | GET /v2/expenses
 32 | Parameter Type  Description
 33 | user_id integer Only return expenses belonging to the user with the given ID.
 34 | client_id integer Only return expenses belonging to the client with the given ID.
 35 | project_id  integer Only return expenses belonging to the project with the given ID.
 36 | is_billed boolean Pass true to only return expenses that have been invoiced and false to return expenses that have not been invoiced.
 37 | updated_since datetime  Only return expenses that have been updated since the given date and time.
 38 | from  date  Only return expenses with a spent_date on or after the given date.
 39 | to  date  Only return expenses with a spent_date on or before the given date.
 40 | page  integer The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)
 41 | per_page  integer The number of records to return per page. Can range between 1 and 2000. (Default: 2000)
 42 | Example Request:
 43 | 
 44 | curl "https://api.harvestapp.com/v2/expenses" \
 45 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
 46 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
 47 |   -H "User-Agent: MyApp ([email protected])"
 48 | Example Response:
 49 | 
 50 | {
 51 |   "expenses":[
 52 |     {
 53 |       "id":15296442,
 54 |       "notes":"Lunch with client",
 55 |       "total_cost":33.35,
 56 |       "units":1.0,
 57 |       "is_closed":false,
 58 |       "is_locked":true,
 59 |       "is_billed":true,
 60 |       "locked_reason":"Expense is invoiced.",
 61 |       "spent_date":"2017-03-03",
 62 |       "created_at":"2017-06-27T15:09:54Z",
 63 |       "updated_at":"2017-06-27T16:47:14Z",
 64 |       "billable":true,
 65 |       "receipt":{
 66 |         "url":"https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/expenses/15296442/receipt",
 67 |         "file_name":"lunch_receipt.gif",
 68 |         "file_size":39410,
 69 |         "content_type":"image/gif"
 70 |       },
 71 |       "user":{
 72 |         "id":1782959,
 73 |         "name":"Kim Allen"
 74 |       },
 75 |       "user_assignment":{
 76 |         "id":125068553,
 77 |         "is_project_manager":true,
 78 |         "is_active":true,
 79 |         "budget":null,
 80 |         "created_at":"2017-06-26T22:32:52Z",
 81 |         "updated_at":"2017-06-26T22:32:52Z",
 82 |         "hourly_rate":100.0
 83 |       },
 84 |       "project":{
 85 |         "id":14307913,
 86 |         "name":"Marketing Website",
 87 |         "code":"MW"
 88 |       },
 89 |       "expense_category":{
 90 |         "id":4195926,
 91 |         "name":"Meals",
 92 |         "unit_price":null,
 93 |         "unit_name":null
 94 |       },
 95 |       "client":{
 96 |         "id":5735774,
 97 |         "name":"ABC Corp",
 98 |         "currency":"USD"
 99 |       },
100 |       "invoice":{
101 |         "id":13150403,
102 |         "number":"1001"
103 |       }
104 |     },
105 |     {
106 |       "id":15296423,
107 |       "notes":"Hotel stay for meeting",
108 |       "total_cost":100.0,
109 |       "units":1.0,
110 |       "is_closed":true,
111 |       "is_locked":true,
112 |       "is_billed":false,
113 |       "locked_reason":"The project is locked for this time period.",
114 |       "spent_date":"2017-03-01",
115 |       "created_at":"2017-06-27T15:09:17Z",
116 |       "updated_at":"2017-06-27T16:47:14Z",
117 |       "billable":true,
118 |       "receipt":null,
119 |       "user":{
120 |         "id":1782959,
121 |         "name":"Kim Allen"
122 |       },
123 |       "user_assignment":{
124 |         "id":125068554,
125 |         "is_project_manager":true,
126 |         "is_active":true,
127 |         "budget":null,
128 |         "created_at":"2017-06-26T22:32:52Z",
129 |         "updated_at":"2017-06-26T22:32:52Z",
130 |         "hourly_rate":100.0
131 |       },
132 |       "project":{
133 |         "id":14308069,
134 |         "name":"Online Store - Phase 1",
135 |         "code":"OS1"
136 |       },
137 |       "expense_category":{
138 |         "id":4197501,
139 |         "name":"Lodging",
140 |         "unit_price":null,
141 |         "unit_name":null
142 |       },
143 |       "client":{
144 |         "id":5735776,
145 |         "name":"123 Industries",
146 |         "currency":"EUR"
147 |       },
148 |       "invoice":null
149 |     }
150 |   ],
151 |   "per_page":2000,
152 |   "total_pages":1,
153 |   "total_entries":2,
154 |   "next_page":null,
155 |   "previous_page":null,
156 |   "page":1,
157 |   "links":{
158 |     "first":"https://api.harvestapp.com/v2/expenses?page=1&per_page=2000",
159 |     "next":null,
160 |     "previous":null,
161 |     "last":"https://api.harvestapp.com/v2/expenses?page=1&per_page=2000"
162 |   }
163 | }
164 | Retrieve an expense⚭
165 | 
166 | Retrieves the expense with the given ID. Returns an expense object and a 200 OK response code if a valid identifier was provided.
167 | 
168 | GET /v2/expenses/{EXPENSE_ID}
169 | Example Request:
170 | 
171 | curl "https://api.harvestapp.com/v2/expenses/15296442" \
172 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
173 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
174 |   -H "User-Agent: MyApp ([email protected])"
175 | Example Response:
176 | 
177 | {
178 |   "id":15296442,
179 |   "notes":"Lunch with client",
180 |   "total_cost":33.35,
181 |   "units":1.0,
182 |   "is_closed":false,
183 |   "is_locked":true,
184 |   "is_billed":true,
185 |   "locked_reason":"Expense is invoiced.",
186 |   "spent_date":"2017-03-03",
187 |   "created_at":"2017-06-27T15:09:54Z",
188 |   "updated_at":"2017-06-27T16:47:14Z",
189 |   "billable":true,
190 |   "receipt":{
191 |     "url":"https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/expenses/15296442/receipt",
192 |     "file_name":"lunch_receipt.gif",
193 |     "file_size":39410,
194 |     "content_type":"image/gif"
195 |   },
196 |   "user":{
197 |     "id":1782959,
198 |     "name":"Kim Allen"
199 |   },
200 |   "user_assignment":{
201 |     "id":125068553,
202 |     "is_project_manager":true,
203 |     "is_active":true,
204 |     "budget":null,
205 |     "created_at":"2017-06-26T22:32:52Z",
206 |     "updated_at":"2017-06-26T22:32:52Z",
207 |     "hourly_rate":100.0
208 |   },
209 |   "project":{
210 |     "id":14307913,
211 |     "name":"Marketing Website",
212 |     "code":"MW"
213 |   },
214 |   "expense_category":{
215 |     "id":4195926,
216 |     "name":"Meals",
217 |     "unit_price":null,
218 |     "unit_name":null
219 |   },
220 |   "client":{
221 |     "id":5735774,
222 |     "name":"ABC Corp",
223 |     "currency":"USD"
224 |   },
225 |   "invoice":{
226 |     "id":13150403,
227 |     "number":"1001"
228 |   }
229 | }
230 | Create an expense⚭
231 | 
232 | Creates a new expense object. Returns an expense object and a 201 Created response code if the call succeeded.
233 | 
234 | POST /v2/expenses
235 | Parameter Type  Required  Description
236 | user_id integer optional  The ID of the user associated with this expense. Defaults to the ID of the currently authenticated user.
237 | project_id  integer required  The ID of the project associated with this expense.
238 | expense_category_id integer required  The ID of the expense category this expense is being tracked against.
239 | spent_date  date  required  Date the expense occurred.
240 | units integer *optional The quantity of units to use in calculating the total_cost of the expense.
241 | total_cost  decimal *optional The total amount of the expense.
242 | notes string  optional  Textual notes used to describe the expense.
243 | billable  boolean optional  Whether this expense is billable or not. Defaults to true.
244 | receipt file  optional  A receipt file to attach to the expense. If including a receipt, you must submit a multipart/form-data request.
245 | * Either units or total_cost is required. units is required if using a unit-based expense category. total_cost is required if not using a unit-based expense category.
246 | 
247 | Example Request:
248 | 
249 | curl "https://api.harvestapp.com/v2/expenses" \
250 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
251 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
252 |   -H "User-Agent: MyApp ([email protected])" \
253 |   -X POST \
254 |   -H "Content-Type: application/json" \
255 |   -d '{"user_id":1782959,"project_id":14308069,"expense_category_id":4195926,"spent_date":"2017-03-01","total_cost":13.59}'
256 | Example Response:
257 | 
258 | {
259 |   "id":15297032,
260 |   "notes":null,
261 |   "total_cost":13.59,
262 |   "units":1.0,
263 |   "is_closed":false,
264 |   "is_locked":false,
265 |   "is_billed":false,
266 |   "locked_reason":null,
267 |   "spent_date":"2017-03-01",
268 |   "created_at":"2017-06-27T15:42:27Z",
269 |   "updated_at":"2017-06-27T15:42:27Z",
270 |   "billable":true,
271 |   "receipt":null,
272 |   "user":{
273 |     "id":1782959,
274 |     "name":"Kim Allen"
275 |   },
276 |   "user_assignment":{
277 |     "id":125068553,
278 |     "is_project_manager":true,
279 |     "is_active":true,
280 |     "budget":null,
281 |     "created_at":"2017-06-26T22:32:52Z",
282 |     "updated_at":"2017-06-26T22:32:52Z",
283 |     "hourly_rate":100.0
284 |   },
285 |   "project":{
286 |     "id":14308069,
287 |     "name":"Online Store - Phase 1",
288 |     "code":"OS1"
289 |   },
290 |   "expense_category":{
291 |     "id":4195926,
292 |     "name":"Meals",
293 |     "unit_price":null,
294 |     "unit_name":null
295 |   },
296 |   "client":{
297 |     "id":5735776,
298 |     "name":"123 Industries",
299 |     "currency":"EUR"
300 |   },
301 |   "invoice":null
302 | }
303 | Update an expense⚭
304 | 
305 | Updates the specific expense by setting the values of the parameters passed. Any parameters not provided will be left unchanged. Returns an expense object and a 200 OK response code if the call succeeded.
306 | 
307 | PATCH /v2/expenses/{EXPENSE_ID}
308 | Parameter Type  Description
309 | project_id  integer The ID of the project associated with this expense.
310 | expense_category_id integer The ID of the expense category this expense is being tracked against.
311 | spent_date  date  Date the expense occurred.
312 | units integer The quantity of units to use in calculating the total_cost of the expense.
313 | total_cost  decimal The total amount of the expense.
314 | notes string  Textual notes used to describe the expense.
315 | billable  boolean Whether this expense is billable or not. Defaults to true.
316 | receipt file  A receipt file to attach to the expense. If including a receipt, you must submit a multipart/form-data request.
317 | delete_receipt  boolean Whether an attached expense receipt should be deleted. Pass true to delete the expense receipt.
318 | Example Request:
319 | 
320 | curl "https://api.harvestapp.com/v2/expenses/15297032" \
321 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
322 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
323 |   -H "User-Agent: MyApp ([email protected])" \
324 |   -X PATCH \
325 |   -F notes="Dinner" \
326 |   -F [email protected]
327 | Example Response:
328 | 
329 | {
330 |   "id":15297032,
331 |   "notes":"Dinner",
332 |   "total_cost":13.59,
333 |   "units":1.0,
334 |   "is_closed":false,
335 |   "is_locked":false,
336 |   "is_billed":false,
337 |   "locked_reason":null,
338 |   "spent_date":"2017-03-01",
339 |   "created_at":"2017-06-27T15:42:27Z",
340 |   "updated_at":"2017-06-27T15:45:51Z",
341 |   "billable":true,
342 |   "receipt":{
343 |     "url":"https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/expenses/15297032/receipt",
344 |     "file_name":"dinner_receipt.gif",
345 |     "file_size":39410,
346 |     "content_type":"image/gif"
347 |   },
348 |   "user":{
349 |     "id":1782959,
350 |     "name":"Kim Allen"
351 |   },
352 |   "user_assignment":{
353 |     "id":125068553,
354 |     "is_project_manager":true,
355 |     "is_active":true,
356 |     "budget":null,
357 |     "created_at":"2017-06-26T22:32:52Z",
358 |     "updated_at":"2017-06-26T22:32:52Z",
359 |     "hourly_rate":100.0
360 |   },
361 |   "project":{
362 |     "id":14308069,
363 |     "name":"Online Store - Phase 1",
364 |     "code":"OS1"
365 |   },
366 |   "expense_category":{
367 |     "id":4195926,
368 |     "name":"Meals",
369 |     "unit_price":null,
370 |     "unit_name":null
371 |   },
372 |   "client":{
373 |     "id":5735776,
374 |     "name":"123 Industries",
375 |     "currency":"EUR"
376 |   },
377 |   "invoice":null
378 | }
379 | Delete an expense⚭
380 | 
381 | Delete an expense. Returns a 200 OK response code if the call succeeded.
382 | 
383 | DELETE /v2/expenses/{EXPENSE_ID}
384 | Example Request:
385 | 
386 | curl "https://api.harvestapp.com/v2/expenses/15297032" \
387 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
388 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
389 |   -H "User-Agent: MyApp ([email protected])" \
390 |   -X DELETE
```

--------------------------------------------------------------------------------
/docs/harvest_api_docs/10_projects/projects.md:
--------------------------------------------------------------------------------

```markdown
  1 | Projects
  2 | 
  3 | The project object⚭
  4 | 
  5 | Attribute	Type	Description
  6 | id	integer	Unique ID for the project.
  7 | client	object	An object containing the project’s client id, name, and currency.
  8 | name	string	Unique name for the project.
  9 | code	string	The code associated with the project.
 10 | is_active	boolean	Whether the project is active or archived.
 11 | is_billable	boolean	Whether the project is billable or not.
 12 | is_fixed_fee	boolean	Whether the project is a fixed-fee project or not.
 13 | bill_by	string	The method by which the project is invoiced.
 14 | hourly_rate	decimal	Rate for projects billed by Project Hourly Rate.
 15 | budget	decimal	The budget in hours for the project when budgeting by time.
 16 | budget_by	string	The method by which the project is budgeted.
 17 | budget_is_monthly	boolean	Option to have the budget reset every month.
 18 | notify_when_over_budget	boolean	Whether Project Managers should be notified when the project goes over budget.
 19 | over_budget_notification_percentage	decimal	Percentage value used to trigger over budget email alerts.
 20 | over_budget_notification_date	date	Date of last over budget notification. If none have been sent, this will be null.
 21 | show_budget_to_all	boolean	Option to show project budget to all employees. Does not apply to Total Project Fee projects.
 22 | cost_budget	decimal	The monetary budget for the project when budgeting by money.
 23 | cost_budget_include_expenses	boolean	Option for budget of Total Project Fees projects to include tracked expenses.
 24 | fee	decimal	The amount you plan to invoice for the project. Only used by fixed-fee projects.
 25 | notes	string	Project notes.
 26 | starts_on	date	Date the project was started.
 27 | ends_on	date	Date the project will end.
 28 | created_at	datetime	Date and time the project was created.
 29 | updated_at	datetime	Date and time the project was last updated.
 30 | Required permissions⚭
 31 | 
 32 | You must be an Administrator or Manager with managed projects in order to interact with the /v2/projects endpoint. Insufficient permissions will result in a 403 Forbidden status code.
 33 | 
 34 | List all projects⚭
 35 | 
 36 | Returns a list of your projects. The projects are returned sorted by creation date, with the most recently created projects appearing first.
 37 | 
 38 | The response contains an object with a projects property that contains an array of up to per_page projects. Each entry in the array is a separate project object. If no more projects are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your projects.
 39 | 
 40 | GET /v2/projects
 41 | Parameter	Type	Description
 42 | is_active	boolean	Pass true to only return active projects and false to return inactive projects.
 43 | client_id	integer	Only return projects belonging to the client with the given ID.
 44 | updated_since	datetime	Only return projects that have been updated since the given date and time.
 45 | page	integer	DEPRECATED The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)
 46 | per_page	integer	The number of records to return per page. Can range between 1 and 2000. (Default: 2000)
 47 | This endpoint supports cursor-based pagination and therefore deprecates the page parameter. For more information, visit the pagination guide.
 48 | Example Request:
 49 | 
 50 | curl "https://api.harvestapp.com/v2/projects" \
 51 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
 52 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
 53 |   -H "User-Agent: MyApp ([email protected])"
 54 | Example Response:
 55 | 
 56 | {
 57 |   "projects":[
 58 |     {
 59 |       "id":14308069,
 60 |       "name":"Online Store - Phase 1",
 61 |       "code":"OS1",
 62 |       "is_active":true,
 63 |       "bill_by":"Project",
 64 |       "budget":200.0,
 65 |       "budget_by":"project",
 66 |       "budget_is_monthly":false,
 67 |       "notify_when_over_budget":true,
 68 |       "over_budget_notification_percentage":80.0,
 69 |       "over_budget_notification_date":null,
 70 |       "show_budget_to_all":false,
 71 |       "created_at":"2017-06-26T21:52:18Z",
 72 |       "updated_at":"2017-06-26T21:54:06Z",
 73 |       "starts_on":"2017-06-01",
 74 |       "ends_on":null,
 75 |       "is_billable":true,
 76 |       "is_fixed_fee":false,
 77 |       "notes":"",
 78 |       "client":{
 79 |         "id":5735776,
 80 |         "name":"123 Industries",
 81 |         "currency":"EUR"
 82 |       },
 83 |       "cost_budget":null,
 84 |       "cost_budget_include_expenses":false,
 85 |       "hourly_rate":100.0,
 86 |       "fee":null
 87 |     },
 88 |     {
 89 |       "id":14307913,
 90 |       "name":"Marketing Website",
 91 |       "code":"MW",
 92 |       "is_active":true,
 93 |       "bill_by":"Project",
 94 |       "budget":50.0,
 95 |       "budget_by":"project",
 96 |       "budget_is_monthly":false,
 97 |       "notify_when_over_budget":true,
 98 |       "over_budget_notification_percentage":80.0,
 99 |       "over_budget_notification_date":null,
100 |       "show_budget_to_all":false,
101 |       "created_at":"2017-06-26T21:36:23Z",
102 |       "updated_at":"2017-06-26T21:54:46Z",
103 |       "starts_on":"2017-01-01",
104 |       "ends_on":"2017-03-31",
105 |       "is_billable":true,
106 |       "is_fixed_fee":false,
107 |       "notes":"",
108 |       "client":{
109 |         "id":5735774,
110 |         "name":"ABC Corp",
111 |         "currency":"USD"
112 |       },
113 |       "cost_budget":null,
114 |       "cost_budget_include_expenses":false,
115 |       "hourly_rate":100.0,
116 |       "fee":null
117 |     }
118 |   ],
119 |   "per_page":2000,
120 |   "total_pages":1,
121 |   "total_entries":2,
122 |   "next_page":null,
123 |   "previous_page":null,
124 |   "page":1,
125 |   "links":{
126 |     "first":"https://api.harvestapp.com/v2/projects?page=1&per_page=2000",
127 |     "next":null,
128 |     "previous":null,
129 |     "last":"https://api.harvestapp.com/v2/projects?page=1&per_page=2000"
130 |   }
131 | }
132 | Retrieve a project⚭
133 | 
134 | Retrieves the project with the given ID. Returns a project object and a 200 OK response code if a valid identifier was provided.
135 | 
136 | GET /v2/projects/{PROJECT_ID}
137 | Example Request:
138 | 
139 | curl "https://api.harvestapp.com/v2/projects/14308069" \
140 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
141 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
142 |   -H "User-Agent: MyApp ([email protected])"
143 | Example Response:
144 | 
145 | {
146 |   "id":14308069,
147 |   "name":"Online Store - Phase 1",
148 |   "code":"OS1",
149 |   "is_active":true,
150 |   "bill_by":"Project",
151 |   "budget":200.0,
152 |   "budget_by":"project",
153 |   "budget_is_monthly":false,
154 |   "notify_when_over_budget":true,
155 |   "over_budget_notification_percentage":80.0,
156 |   "over_budget_notification_date":null,
157 |   "show_budget_to_all":false,
158 |   "created_at":"2017-06-26T21:52:18Z",
159 |   "updated_at":"2017-06-26T21:54:06Z",
160 |   "starts_on":"2017-06-01",
161 |   "ends_on":null,
162 |   "is_billable":true,
163 |   "is_fixed_fee":false,
164 |   "notes":"",
165 |   "client":{
166 |     "id":5735776,
167 |     "name":"123 Industries",
168 |     "currency":"EUR"
169 |   },
170 |   "cost_budget":null,
171 |   "cost_budget_include_expenses":false,
172 |   "hourly_rate":100.0,
173 |   "fee":null
174 | }
175 | Create a project⚭
176 | 
177 | Creates a new project object. Returns a project object and a 201 Created response code if the call succeeded.
178 | 
179 | POST /v2/projects
180 | Parameter	Type	Required	Description
181 | client_id	integer	required	The ID of the client to associate this project with.
182 | name	string	required	The name of the project.
183 | code	string	optional	The code associated with the project.
184 | is_active	boolean	optional	Whether the project is active or archived. Defaults to true.
185 | is_billable	boolean	required	Whether the project is billable or not.
186 | is_fixed_fee	boolean	optional	Whether the project is a fixed-fee project or not.
187 | bill_by	string	required	The method by which the project is invoiced. Options: Project, Tasks, People, or none.
188 | hourly_rate	decimal	optional	Rate for projects billed by Project Hourly Rate.
189 | budget	decimal	optional	The budget in hours for the project when budgeting by time.
190 | budget_by	string	required	The method by which the project is budgeted. Options: project (Hours Per Project), project_cost (Total Project Fees), task (Hours Per Task), task_fees (Fees Per Task), person (Hours Per Person), none (No Budget).
191 | budget_is_monthly	boolean	optional	Option to have the budget reset every month. Defaults to false.
192 | notify_when_over_budget	boolean	optional	Whether Project Managers should be notified when the project goes over budget. Defaults to false.
193 | over_budget_notification_percentage	decimal	optional	Percentage value used to trigger over budget email alerts. Example: use 10.0 for 10.0%.
194 | show_budget_to_all	boolean	optional	Option to show project budget to all employees. Does not apply to Total Project Fee projects. Defaults to false.
195 | cost_budget	decimal	optional	The monetary budget for the project when budgeting by money.
196 | cost_budget_include_expenses	boolean	optional	Option for budget of Total Project Fees projects to include tracked expenses. Defaults to false.
197 | fee	decimal	optional	The amount you plan to invoice for the project. Only used by fixed-fee projects.
198 | notes	string	optional	Project notes.
199 | starts_on	date	optional	Date the project was started.
200 | ends_on	date	optional	Date the project will end.
201 | Example Request:
202 | 
203 | curl "https://api.harvestapp.com/v2/projects" \
204 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
205 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
206 |   -H "User-Agent: MyApp ([email protected])" \
207 |   -X POST \
208 |   -H "Content-Type: application/json" \
209 |   -d '{"client_id":5735776,"name":"Your New Project","is_billable":true,"bill_by":"Project","hourly_rate":100.0,"budget_by":"project","budget":10000}'
210 | Example Response:
211 | 
212 | {
213 |   "id":14308112,
214 |   "name":"Your New Project",
215 |   "code":null,
216 |   "is_active":true,
217 |   "bill_by":"Project",
218 |   "budget":10000.0,
219 |   "budget_by":"project",
220 |   "budget_is_monthly":false,
221 |   "notify_when_over_budget":false,
222 |   "over_budget_notification_percentage":80.0,
223 |   "over_budget_notification_date":null,
224 |   "show_budget_to_all":false,
225 |   "created_at":"2017-06-26T21:56:52Z",
226 |   "updated_at":"2017-06-26T21:56:52Z",
227 |   "starts_on":null,
228 |   "ends_on":null,
229 |   "is_billable":true,
230 |   "is_fixed_fee":false,
231 |   "notes":"",
232 |   "client":{
233 |     "id":5735776,
234 |     "name":"123 Industries",
235 |     "currency":"EUR"
236 |   },
237 |   "cost_budget":null,
238 |   "cost_budget_include_expenses":false,
239 |   "hourly_rate":100.0,
240 |   "fee":null
241 | }
242 | Update a project⚭
243 | 
244 | Updates the specific project by setting the values of the parameters passed. Any parameters not provided will be left unchanged. Returns a project object and a 200 OK response code if the call succeeded.
245 | 
246 | PATCH /v2/projects/{PROJECT_ID}
247 | Parameter	Type	Description
248 | client_id	integer	The ID of the client to associate this project with.
249 | name	string	The name of the project.
250 | code	string	The code associated with the project.
251 | is_active	boolean	Whether the project is active or archived. Defaults to true.
252 | is_billable	boolean	Whether the project is billable or not.
253 | is_fixed_fee	boolean	Whether the project is a fixed-fee project or not.
254 | bill_by	string	The method by which the project is invoiced. Options: Project, Tasks, People, or none.
255 | hourly_rate	decimal	Rate for projects billed by Project Hourly Rate.
256 | budget	decimal	The budget in hours for the project when budgeting by time.
257 | budget_by	string	The method by which the project is budgeted. Options: project (Hours Per Project), project_cost (Total Project Fees), task (Hours Per Task), task_fees (Fees Per Task), person (Hours Per Person), none (No Budget).
258 | budget_is_monthly	boolean	Option to have the budget reset every month. Defaults to false.
259 | notify_when_over_budget	boolean	Whether Project Managers should be notified when the project goes over budget. Defaults to false.
260 | over_budget_notification_percentage	decimal	Percentage value used to trigger over budget email alerts. Example: use 10.0 for 10.0%.
261 | show_budget_to_all	boolean	Option to show project budget to all employees. Does not apply to Total Project Fee projects. Defaults to false.
262 | cost_budget	decimal	The monetary budget for the project when budgeting by money.
263 | cost_budget_include_expenses	boolean	Option for budget of Total Project Fees projects to include tracked expenses. Defaults to false.
264 | fee	decimal	The amount you plan to invoice for the project. Only used by fixed-fee projects.
265 | notes	string	Project notes.
266 | starts_on	date	Date the project was started.
267 | ends_on	date	Date the project will end.
268 | Example Request:
269 | 
270 | curl "https://api.harvestapp.com/v2/projects/14308112" \
271 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
272 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
273 |   -H "User-Agent: MyApp ([email protected])" \
274 |   -X PATCH \
275 |   -H "Content-Type: application/json" \
276 |   -d '{"name":"New project name"}'
277 | Example Response:
278 | 
279 | {
280 |   "id":14308112,
281 |   "name":"New project name",
282 |   "code":null,
283 |   "is_active":true,
284 |   "bill_by":"Project",
285 |   "budget":10000.0,
286 |   "budget_by":"project",
287 |   "budget_is_monthly":false,
288 |   "notify_when_over_budget":false,
289 |   "over_budget_notification_percentage":80.0,
290 |   "over_budget_notification_date":null,
291 |   "show_budget_to_all":false,
292 |   "created_at":"2017-06-26T21:56:52Z",
293 |   "updated_at":"2017-06-26T21:57:20Z",
294 |   "starts_on":null,
295 |   "ends_on":null,
296 |   "is_billable":true,
297 |   "is_fixed_fee":false,
298 |   "notes":"",
299 |   "client":{
300 |     "id":5735776,
301 |     "name":"123 Industries",
302 |     "currency":"EUR"
303 |   },
304 |   "cost_budget":null,
305 |   "cost_budget_include_expenses":false,
306 |   "hourly_rate":100.0,
307 |   "fee":null
308 | }
309 | Delete a project⚭
310 | 
311 | Deletes a project and any time entries or expenses tracked to it. However, invoices associated with the project will not be deleted. If you don’t want the project’s time entries and expenses to be deleted, you should archive the project instead.
312 | 
313 | DELETE /v2/projects/{PROJECT_ID}
314 | Example Request:
315 | 
316 | curl "https://api.harvestapp.com/v2/projects/14308112" \
317 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
318 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
319 |   -H "User-Agent: MyApp ([email protected])" \
320 |   -X DELETE
321 | 
```

--------------------------------------------------------------------------------
/docs/harvest_api_docs/10_projects/project_user_assignments.md:
--------------------------------------------------------------------------------

```markdown
  1 | Project User Assignments
  2 | 
  3 | The user assignment object⚭
  4 | 
  5 | Attribute	Type	Description
  6 | id	integer	Unique ID for the user assignment.
  7 | project	object	An object containing the id, name, and code of the associated project.
  8 | user	object	An object containing the id and name of the associated user.
  9 | is_active	boolean	Whether the user assignment is active or archived.
 10 | is_project_manager	boolean	Determines if the user has Project Manager permissions for the project.
 11 | use_default_rates	boolean	Determines which billable rate(s) will be used on the project for this user when bill_by is People. When true, the project will use the user’s default billable rates. When false, the project will use the custom rate defined on this user assignment.
 12 | hourly_rate	decimal	Custom rate used when the project’s bill_by is People and use_default_rates is false.
 13 | budget	decimal	Budget used when the project’s budget_by is person.
 14 | created_at	datetime	Date and time the user assignment was created.
 15 | updated_at	datetime	Date and time the user assignment was last updated.
 16 | Required permissions⚭
 17 | 
 18 | You must be an Administrator or Manager with assigned teammates or managed projects in order to interact with the /v2/user_assignments endpoint. Insufficient permissions will result in a 403 Forbidden status code.
 19 | 
 20 | List all user assignments⚭
 21 | 
 22 | Returns a list of your projects user assignments, active and archived. The user assignments are returned sorted by creation date, with the most recently created user assignments appearing first.
 23 | 
 24 | The response contains an object with a user_assignments property that contains an array of up to per_page user assignments. Each entry in the array is a separate user assignment object. If no more user assignments are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your user assignments.
 25 | 
 26 | GET /v2/user_assignments
 27 | Parameter	Type	Description
 28 | user_id	integer	Only return user assignments belonging to the user with the given ID.
 29 | is_active	boolean	Pass true to only return active user assignments and false to return inactive user assignments.
 30 | updated_since	datetime	Only return user assignments that have been updated since the given date and time.
 31 | page	integer	DEPRECATED The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)
 32 | per_page	integer	The number of records to return per page. Can range between 1 and 2000. (Default: 2000)
 33 | This endpoint supports cursor-based pagination and therefore deprecates the page parameter. For more information, visit the pagination guide.
 34 | Example Request:
 35 | 
 36 | curl "https://api.harvestapp.com/v2/user_assignments" \
 37 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
 38 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
 39 |   -H "User-Agent: MyApp ([email protected])"
 40 | Example Response:
 41 | 
 42 | {
 43 |   "user_assignments":[
 44 |     {
 45 |       "id":130403297,
 46 |       "is_project_manager":true,
 47 |       "is_active":true,
 48 |       "use_default_rates":false,
 49 |       "budget":null,
 50 |       "created_at":"2017-08-22T17:36:54Z",
 51 |       "updated_at":"2017-08-22T17:36:54Z",
 52 |       "hourly_rate":100.0,
 53 |       "project":{
 54 |         "id":14808188,
 55 |         "name":"Task Force",
 56 |         "code":"TF"
 57 |       },
 58 |       "user":{
 59 |         "id":1782959,
 60 |         "name":"Kim Allen"
 61 |       }
 62 |     },
 63 |     {
 64 |       "id":130403296,
 65 |       "is_project_manager":true,
 66 |       "is_active":true,
 67 |       "use_default_rates":true,
 68 |       "budget":null,
 69 |       "created_at":"2017-08-22T17:36:54Z",
 70 |       "updated_at":"2017-08-22T17:36:54Z",
 71 |       "hourly_rate":100.0,
 72 |       "project":{
 73 |         "id":14808188,
 74 |         "name":"Task Force",
 75 |         "code":"TF"
 76 |       },
 77 |       "user":{
 78 |         "id":1795925,
 79 |         "name":"Jason Dew"
 80 |       }
 81 |     },
 82 |     {
 83 |       "id":125068554,
 84 |       "is_project_manager":true,
 85 |       "is_active":true,
 86 |       "use_default_rates":true,
 87 |       "budget":null,
 88 |       "created_at":"2017-06-26T22:32:52Z",
 89 |       "updated_at":"2017-06-26T22:32:52Z",
 90 |       "hourly_rate":100.0,
 91 |       "project":{
 92 |         "id":14308069,
 93 |         "name":"Online Store - Phase 1",
 94 |         "code":"OS1"
 95 |       },
 96 |       "user":{
 97 |         "id":1782959,
 98 |         "name":"Kim Allen"
 99 |       }
100 |     },
101 |     {
102 |       "id":125068553,
103 |       "is_project_manager":true,
104 |       "is_active":true,
105 |       "use_default_rates":true,
106 |       "budget":null,
107 |       "created_at":"2017-06-26T22:32:52Z",
108 |       "updated_at":"2017-06-26T22:32:52Z",
109 |       "hourly_rate":100.0,
110 |       "project":{
111 |         "id":14307913,
112 |         "name":"Marketing Website",
113 |         "code":"MW"
114 |       },
115 |       "user":{
116 |         "id":1782959,
117 |         "name":"Kim Allen"
118 |       }
119 |     },
120 |     {
121 |       "id":125066109,
122 |       "is_project_manager":true,
123 |       "is_active":true,
124 |       "use_default_rates":false,
125 |       "budget":null,
126 |       "created_at":"2017-06-26T21:52:18Z",
127 |       "updated_at":"2017-06-26T21:52:18Z",
128 |       "hourly_rate":100.0,
129 |       "project":{
130 |         "id":14308069,
131 |         "name":"Online Store - Phase 1",
132 |         "code":"OS1"
133 |       },
134 |       "user":{
135 |         "id":1782884,
136 |         "name":"Jeremy Israelsen"
137 |       }
138 |     },
139 |     {
140 |       "id":125063975,
141 |       "is_project_manager":true,
142 |       "is_active":true,
143 |       "use_default_rates":true,
144 |       "budget":null,
145 |       "created_at":"2017-06-26T21:36:23Z",
146 |       "updated_at":"2017-06-26T21:36:23Z",
147 |       "hourly_rate":100.0,
148 |       "project":{
149 |         "id":14307913,
150 |         "name":"Marketing Website",
151 |         "code":"MW"
152 |       },
153 |       "user":{
154 |         "id":1782884,
155 |         "name":"Jeremy Israelsen"
156 |       }
157 |     }
158 |   ],
159 |   "per_page":2000,
160 |   "total_pages":1,
161 |   "total_entries":6,
162 |   "next_page":null,
163 |   "previous_page":null,
164 |   "page":1,
165 |   "links":{
166 |     "first":"https://api.harvestapp.com/v2/user_assignments?page=1&per_page=2000",
167 |     "next":null,
168 |     "previous":null,
169 |     "last":"https://api.harvestapp.com/v2/user_assignments?page=1&per_page=2000"
170 |   }
171 | }
172 | List all user assignments for a specific project⚭
173 | 
174 | Returns a list of user assignments for the project identified by PROJECT_ID. The user assignments are returned sorted by creation date, with the most recently created user assignments appearing first.
175 | 
176 | The response contains an object with a user_assignments property that contains an array of up to per_page user assignments. Each entry in the array is a separate user assignment object. If no more user assignments are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your user assignments.
177 | 
178 | GET /v2/projects/{PROJECT_ID}/user_assignments
179 | Parameter	Type	Description
180 | user_id	integer	Only return user assignments belonging to the user with the given ID.
181 | is_active	boolean	Pass true to only return active user assignments and false to return inactive user assignments.
182 | updated_since	datetime	Only return user assignments that have been updated since the given date and time.
183 | page	integer	The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)
184 | per_page	integer	The number of records to return per page. Can range between 1 and 2000. (Default: 2000)
185 | Example Request:
186 | 
187 | curl "https://api.harvestapp.com/v2/projects/14308069/user_assignments" \
188 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
189 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
190 |   -H "User-Agent: MyApp ([email protected])"
191 | Example Response:
192 | 
193 | {
194 |   "user_assignments":[
195 |     {
196 |       "id":125068554,
197 |       "is_project_manager":true,
198 |       "is_active":true,
199 |       "use_default_rates":true,
200 |       "budget":null,
201 |       "created_at":"2017-06-26T22:32:52Z",
202 |       "updated_at":"2017-06-26T22:32:52Z",
203 |       "hourly_rate":100.0,
204 |       "project":{
205 |         "id":14308069,
206 |         "name":"Online Store - Phase 1",
207 |         "code":"OS1"
208 |       },
209 |       "user":{
210 |         "id":1782959,
211 |         "name":"Kim Allen"
212 |       }
213 |     },
214 |     {
215 |       "id":125066109,
216 |       "is_project_manager":true,
217 |       "is_active":true,
218 |       "use_default_rates":false,
219 |       "budget":null,
220 |       "created_at":"2017-06-26T21:52:18Z",
221 |       "updated_at":"2017-06-26T21:52:18Z",
222 |       "hourly_rate":100.0,
223 |       "project":{
224 |         "id":14308069,
225 |         "name":"Online Store - Phase 1",
226 |         "code":"OS1"
227 |       },
228 |       "user":{
229 |         "id":1782884,
230 |         "name":"Jeremy Israelsen"
231 |       }
232 |     }
233 |   ],
234 |   "per_page":2000,
235 |   "total_pages":1,
236 |   "total_entries":2,
237 |   "next_page":null,
238 |   "previous_page":null,
239 |   "page":1,
240 |   "links":{
241 |     "first":"https://api.harvestapp.com/v2/projects/14308069/user_assignments?page=1&per_page=2000",
242 |     "next":null,
243 |     "previous":null,
244 |     "last":"https://api.harvestapp.com/v2/projects/14308069/user_assignments?page=1&per_page=2000"
245 |   }
246 | }
247 | Retrieve a user assignment⚭
248 | 
249 | Retrieves the user assignment with the given ID. Returns a user assignment object and a 200 OK response code if a valid identifier was provided.
250 | 
251 | GET /v2/projects/{PROJECT_ID}/user_assignments/{USER_ASSIGNMENT_ID}
252 | Example Request:
253 | 
254 | curl "https://api.harvestapp.com/v2/projects/14308069/user_assignments/125068554" \
255 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
256 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
257 |   -H "User-Agent: MyApp ([email protected])"
258 | Example Response:
259 | 
260 | {
261 |   "id":125068554,
262 |   "is_project_manager":true,
263 |   "is_active":true,
264 |   "use_default_rates":true,
265 |   "budget":null,
266 |   "created_at":"2017-06-26T22:32:52Z",
267 |   "updated_at":"2017-06-26T22:32:52Z",
268 |   "hourly_rate":100.0,
269 |   "project":{
270 |     "id":14308069,
271 |     "name":"Online Store - Phase 1",
272 |     "code":"OS1"
273 |   },
274 |   "user":{
275 |     "id":1782959,
276 |     "name":"Kim Allen"
277 |   }
278 | }
279 | Create a user assignment⚭
280 | 
281 | Creates a new user assignment object. Returns a user assignment object and a 201 Created response code if the call succeeded.
282 | 
283 | POST /v2/projects/{PROJECT_ID}/user_assignments
284 | Parameter	Type	Required	Description
285 | user_id	integer	required	The ID of the user to associate with the project.
286 | is_active	boolean	optional	Whether the user assignment is active or archived. Defaults to true.
287 | is_project_manager	boolean	optional	Determines if the user has Project Manager permissions for the project. Defaults to false for users with Regular User permissions and true for those with Project Managers or Administrator permissions.
288 | use_default_rates	boolean	optional	Determines which billable rate(s) will be used on the project for this user when bill_by is People. When true, the project will use the user’s default billable rates. When false, the project will use the custom rate defined on this user assignment. Defaults to true.
289 | hourly_rate	decimal	optional	Custom rate used when the project’s bill_by is People and use_default_rates is false. Defaults to 0.
290 | budget	decimal	optional	Budget used when the project’s budget_by is person.
291 | Example Request:
292 | 
293 | curl "https://api.harvestapp.com/v2/projects/14308069/user_assignments" \
294 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
295 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
296 |   -H "User-Agent: MyApp ([email protected])" \
297 |   -X POST \
298 |   -H "Content-Type: application/json" \
299 |   -d '{"user_id":1782974,"use_default_rates":false,"hourly_rate":75.50}'
300 | Example Response:
301 | 
302 | {
303 |   "id":125068758,
304 |   "is_project_manager":false,
305 |   "is_active":true,
306 |   "use_default_rates":false,
307 |   "budget":null,
308 |   "created_at":"2017-06-26T22:36:01Z",
309 |   "updated_at":"2017-06-26T22:36:01Z",
310 |   "hourly_rate":75.5,
311 |   "project":{
312 |     "id":14308069,
313 |     "name":"Online Store - Phase 1",
314 |     "code":"OS1"
315 |   },
316 |   "user":{
317 |     "id":1782974,
318 |     "name":"Jim Allen"
319 |   }
320 | }
321 | Update a user assignment⚭
322 | 
323 | Updates the specific user assignment by setting the values of the parameters passed. Any parameters not provided will be left unchanged. Returns a user assignment object and a 200 OK response code if the call succeeded.
324 | 
325 | PATCH /v2/projects/{PROJECT_ID}/user_assignments/{USER_ASSIGNMENT_ID}
326 | Parameter	Type	Description
327 | is_active	boolean	Whether the user assignment is active or archived.
328 | is_project_manager	boolean	Determines if the user has Project Manager permissions for the project.
329 | use_default_rates	boolean	Determines which billable rate(s) will be used on the project for this user when bill_by is People. When true, the project will use the user’s default billable rates. When false, the project will use the custom rate defined on this user assignment.
330 | hourly_rate	decimal	Custom rate used when the project’s bill_by is People and use_default_rates is false.
331 | budget	decimal	Budget used when the project’s budget_by is person.
332 | Example Request:
333 | 
334 | curl "https://api.harvestapp.com/v2/projects/14308069/user_assignments/125068758" \
335 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
336 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
337 |   -H "User-Agent: MyApp ([email protected])" \
338 |   -X PATCH \
339 |   -H "Content-Type: application/json" \
340 |   -d '{"budget":120}'
341 | Example Response:
342 | 
343 | {
344 |   "id":125068758,
345 |   "is_project_manager":false,
346 |   "is_active":true,
347 |   "use_default_rates":false,
348 |   "budget":120.0,
349 |   "created_at":"2017-06-26T22:36:01Z",
350 |   "updated_at":"2017-06-26T22:36:35Z",
351 |   "hourly_rate":75.5,
352 |   "project":{
353 |     "id":14308069,
354 |     "name":"Online Store - Phase 1",
355 |     "code":"OS1"
356 |   },
357 |   "user":{
358 |     "id":1782974,
359 |     "name":"Jim Allen"
360 |   }
361 | }
362 | Delete a user assignment⚭
363 | 
364 | Delete a user assignment. Deleting a user assignment is only possible if it has no time entries or expenses associated with it. Returns a 200 OK response code if the call succeeded.
365 | 
366 | DELETE /v2/projects/{PROJECT_ID}/user_assignments/{USER_ASSIGNMENT_ID}
367 | Example Request:
368 | 
369 | curl "https://api.harvestapp.com/v2/projects/14308069/user_assignments/125068758" \
370 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
371 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
372 |   -H "User-Agent: MyApp ([email protected])" \
373 |   -X DELETE
374 | 
```

--------------------------------------------------------------------------------
/docs/harvest_api_docs/10_projects/project_task_assignments.md:
--------------------------------------------------------------------------------

```markdown
  1 | Project Task Assignments
  2 | 
  3 | Admin or Project Manager permissions required.
  4 | 
  5 | The task assignment object⚭
  6 | 
  7 | Attribute	Type	Description
  8 | id	integer	Unique ID for the task assignment.
  9 | project	object	An object containing the id, name, and code of the associated project.
 10 | task	object	An object containing the id and name of the associated task.
 11 | is_active	boolean	Whether the task assignment is active or archived.
 12 | billable	boolean	Whether the task assignment is billable or not. For example: if set to true, all time tracked on this project for the associated task will be marked as billable.
 13 | hourly_rate	decimal	Rate used when the project’s bill_by is Tasks.
 14 | budget	decimal	Budget used when the project’s budget_by is task or task_fees.
 15 | created_at	datetime	Date and time the task assignment was created.
 16 | updated_at	datetime	Date and time the task assignment was last updated.
 17 | List all task assignments⚭
 18 | 
 19 | Returns a list of your task assignments. The task assignments are returned sorted by creation date, with the most recently created task assignments appearing first.
 20 | 
 21 | The response contains an object with a task_assignments property that contains an array of up to per_page task assignments. Each entry in the array is a separate task assignment object. If no more task assignments are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your task assignments.
 22 | 
 23 | GET /v2/task_assignments
 24 | Parameter	Type	Description
 25 | is_active	boolean	Pass true to only return active task assignments and false to return inactive task assignments.
 26 | updated_since	datetime	Only return task assignments that have been updated since the given date and time.
 27 | page	integer	DEPRECATED The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)
 28 | per_page	integer	The number of records to return per page. Can range between 1 and 2000. (Default: 2000)
 29 | This endpoint supports cursor-based pagination and therefore deprecates the page parameter. For more information, visit the pagination guide.
 30 | Example Request:
 31 | 
 32 | curl "https://api.harvestapp.com/v2/task_assignments" \
 33 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
 34 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
 35 |   -H "User-Agent: MyApp ([email protected])"
 36 | Example Response:
 37 | 
 38 | {
 39 |   "task_assignments":[
 40 |     {
 41 |       "id":160726647,
 42 |       "billable":false,
 43 |       "is_active":true,
 44 |       "created_at":"2017-08-22T17:36:54Z",
 45 |       "updated_at":"2017-08-22T17:36:54Z",
 46 |       "hourly_rate":100.0,
 47 |       "budget":null,
 48 |       "project":{
 49 |         "id":14808188,
 50 |         "name":"Task Force",
 51 |         "code":"TF"
 52 |       },
 53 |       "task":{
 54 |         "id":8083369,
 55 |         "name":"Research"
 56 |       }
 57 |     },
 58 |     {
 59 |       "id":160726646,
 60 |       "billable":true,
 61 |       "is_active":true,
 62 |       "created_at":"2017-08-22T17:36:54Z",
 63 |       "updated_at":"2017-08-22T17:36:54Z",
 64 |       "hourly_rate":100.0,
 65 |       "budget":null,
 66 |       "project":{
 67 |         "id":14808188,
 68 |         "name":"Task Force",
 69 |         "code":"TF"
 70 |       },
 71 |       "task":{
 72 |         "id":8083368,
 73 |         "name":"Project Management"
 74 |       }
 75 |     },
 76 |     {
 77 |       "id":160726645,
 78 |       "billable":true,
 79 |       "is_active":true,
 80 |       "created_at":"2017-08-22T17:36:54Z",
 81 |       "updated_at":"2017-08-22T17:36:54Z",
 82 |       "hourly_rate":100.0,
 83 |       "budget":null,
 84 |       "project":{
 85 |         "id":14808188,
 86 |         "name":"Task Force",
 87 |         "code":"TF"
 88 |       },
 89 |       "task":{
 90 |         "id":8083366,
 91 |         "name":"Programming"
 92 |       }
 93 |     },
 94 |     {
 95 |       "id":160726644,
 96 |       "billable":true,
 97 |       "is_active":true,
 98 |       "created_at":"2017-08-22T17:36:54Z",
 99 |       "updated_at":"2017-08-22T17:36:54Z",
100 |       "hourly_rate":100.0,
101 |       "budget":null,
102 |       "project":{
103 |         "id":14808188,
104 |         "name":"Task Force",
105 |         "code":"TF"
106 |       },
107 |       "task":{
108 |         "id":8083365,
109 |         "name":"Graphic Design"
110 |       }
111 |     },
112 |     {
113 |       "id":155505153,
114 |       "billable":false,
115 |       "is_active":true,
116 |       "created_at":"2017-06-26T21:53:20Z",
117 |       "updated_at":"2017-06-26T21:54:31Z",
118 |       "hourly_rate":100.0,
119 |       "budget":null,
120 |       "project":{
121 |         "id":14307913,
122 |         "name":"Marketing Website",
123 |         "code":"MW"
124 |       },
125 |       "task":{
126 |         "id":8083369,
127 |         "name":"Research"
128 |       }
129 |     },
130 |     {
131 |       "id":155505016,
132 |       "billable":false,
133 |       "is_active":true,
134 |       "created_at":"2017-06-26T21:52:18Z",
135 |       "updated_at":"2017-06-26T21:54:06Z",
136 |       "hourly_rate":100.0,
137 |       "budget":null,
138 |       "project":{
139 |         "id":14308069,
140 |         "name":"Online Store - Phase 1",
141 |         "code":"OS1"
142 |       },
143 |       "task":{
144 |         "id":8083369,
145 |         "name":"Research"
146 |       }
147 |     },
148 |     {
149 |       "id":155505015,
150 |       "billable":true,
151 |       "is_active":true,
152 |       "created_at":"2017-06-26T21:52:18Z",
153 |       "updated_at":"2017-06-26T21:52:18Z",
154 |       "hourly_rate":100.0,
155 |       "budget":null,
156 |       "project":{
157 |         "id":14308069,
158 |         "name":"Online Store - Phase 1",
159 |         "code":"OS1"
160 |       },
161 |       "task":{
162 |         "id":8083368,
163 |         "name":"Project Management"
164 |       }
165 |     },
166 |     {
167 |       "id":155505014,
168 |       "billable":true,
169 |       "is_active":true,
170 |       "created_at":"2017-06-26T21:52:18Z",
171 |       "updated_at":"2017-06-26T21:52:18Z",
172 |       "hourly_rate":100.0,
173 |       "budget":null,
174 |       "project":{
175 |         "id":14308069,
176 |         "name":"Online Store - Phase 1",
177 |         "code":"OS1"
178 |       },
179 |       "task":{
180 |         "id":8083366,
181 |         "name":"Programming"
182 |       }
183 |     },
184 |     {
185 |       "id":155505013,
186 |       "billable":true,
187 |       "is_active":true,
188 |       "created_at":"2017-06-26T21:52:18Z",
189 |       "updated_at":"2017-06-26T21:52:18Z",
190 |       "hourly_rate":100.0,
191 |       "budget":null,
192 |       "project":{
193 |         "id":14308069,
194 |         "name":"Online Store - Phase 1",
195 |         "code":"OS1"
196 |       },
197 |       "task":{
198 |         "id":8083365,
199 |         "name":"Graphic Design"
200 |       }
201 |     },
202 |     {
203 |       "id":155502711,
204 |       "billable":true,
205 |       "is_active":true,
206 |       "created_at":"2017-06-26T21:36:23Z",
207 |       "updated_at":"2017-06-26T21:36:23Z",
208 |       "hourly_rate":100.0,
209 |       "budget":null,
210 |       "project":{
211 |         "id":14307913,
212 |         "name":"Marketing Website",
213 |         "code":"MW"
214 |       },
215 |       "task":{
216 |         "id":8083368,
217 |         "name":"Project Management"
218 |       }
219 |     },
220 |     {
221 |       "id":155502710,
222 |       "billable":true,
223 |       "is_active":true,
224 |       "created_at":"2017-06-26T21:36:23Z",
225 |       "updated_at":"2017-06-26T21:36:23Z",
226 |       "hourly_rate":100.0,
227 |       "budget":null,
228 |       "project":{
229 |         "id":14307913,
230 |         "name":"Marketing Website",
231 |         "code":"MW"
232 |       },
233 |       "task":{
234 |         "id":8083366,
235 |         "name":"Programming"
236 |       }
237 |     },
238 |     {
239 |       "id":155502709,
240 |       "billable":true,
241 |       "is_active":true,
242 |       "created_at":"2017-06-26T21:36:23Z",
243 |       "updated_at":"2017-06-26T21:36:23Z",
244 |       "hourly_rate":100.0,
245 |       "budget":null,
246 |       "project":{
247 |         "id":14307913,
248 |         "name":"Marketing Website",
249 |         "code":"MW"
250 |       },
251 |       "task":{
252 |         "id":8083365,
253 |         "name":"Graphic Design"
254 |       }
255 |     }
256 |   ],
257 |   "per_page":2000,
258 |   "total_pages":1,
259 |   "total_entries":12,
260 |   "next_page":null,
261 |   "previous_page":null,
262 |   "page":1,
263 |   "links":{
264 |     "first":"https://api.harvestapp.com/v2/task_assignments?page=1&per_page=2000",
265 |     "next":null,
266 |     "previous":null,
267 |     "last":"https://api.harvestapp.com/v2/task_assignments?page=1&per_page=2000"
268 |   }
269 | }
270 | List all task assignments for a specific project⚭
271 | 
272 | Returns a list of your task assignments for the project identified by PROJECT_ID. The task assignments are returned sorted by creation date, with the most recently created task assignments appearing first.
273 | 
274 | The response contains an object with a task_assignments property that contains an array of up to per_page task assignments. Each entry in the array is a separate task assignment object. If no more task assignments are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your task assignments.
275 | 
276 | GET /v2/projects/{PROJECT_ID}/task_assignments
277 | Parameter	Type	Description
278 | is_active	boolean	Pass true to only return active task assignments and false to return inactive task assignments.
279 | updated_since	datetime	Only return task assignments that have been updated since the given date and time.
280 | page	integer	The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)
281 | per_page	integer	The number of records to return per page. Can range between 1 and 2000. (Default: 2000)
282 | Example Request:
283 | 
284 | curl "https://api.harvestapp.com/v2/projects/14308069/task_assignments" \
285 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
286 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
287 |   -H "User-Agent: MyApp ([email protected])"
288 | Example Response:
289 | 
290 | {
291 |   "task_assignments":[
292 |     {
293 |       "id":155505016,
294 |       "billable":false,
295 |       "is_active":true,
296 |       "created_at":"2017-06-26T21:52:18Z",
297 |       "updated_at":"2017-06-26T21:54:06Z",
298 |       "hourly_rate":100.0,
299 |       "budget":null,
300 |       "project":{
301 |         "id":14308069,
302 |         "name":"Online Store - Phase 1",
303 |         "code":"OS1"
304 |       },
305 |       "task":{
306 |         "id":8083369,
307 |         "name":"Research"
308 |       }
309 |     },
310 |     {
311 |       "id":155505015,
312 |       "billable":true,
313 |       "is_active":true,
314 |       "created_at":"2017-06-26T21:52:18Z",
315 |       "updated_at":"2017-06-26T21:52:18Z",
316 |       "hourly_rate":100.0,
317 |       "budget":null,
318 |       "project":{
319 |         "id":14308069,
320 |         "name":"Online Store - Phase 1",
321 |         "code":"OS1"
322 |       },
323 |       "task":{
324 |         "id":8083368,
325 |         "name":"Project Management"
326 |       }
327 |     },
328 |     {
329 |       "id":155505014,
330 |       "billable":true,
331 |       "is_active":true,
332 |       "created_at":"2017-06-26T21:52:18Z",
333 |       "updated_at":"2017-06-26T21:52:18Z",
334 |       "hourly_rate":100.0,
335 |       "budget":null,
336 |       "project":{
337 |         "id":14308069,
338 |         "name":"Online Store - Phase 1",
339 |         "code":"OS1"
340 |       },
341 |       "task":{
342 |         "id":8083366,
343 |         "name":"Programming"
344 |       }
345 |     },
346 |     {
347 |       "id":155505013,
348 |       "billable":true,
349 |       "is_active":true,
350 |       "created_at":"2017-06-26T21:52:18Z",
351 |       "updated_at":"2017-06-26T21:52:18Z",
352 |       "hourly_rate":100.0,
353 |       "budget":null,
354 |       "project":{
355 |         "id":14308069,
356 |         "name":"Online Store - Phase 1",
357 |         "code":"OS1"
358 |       },
359 |       "task":{
360 |         "id":8083365,
361 |         "name":"Graphic Design"
362 |       }
363 |     }
364 |   ],
365 |   "per_page":2000,
366 |   "total_pages":1,
367 |   "total_entries":4,
368 |   "next_page":null,
369 |   "previous_page":null,
370 |   "page":1,
371 |   "links":{
372 |     "first":"https://api.harvestapp.com/v2/projects/14308069/task_assignments?page=1&per_page=2000",
373 |     "next":null,
374 |     "previous":null,
375 |     "last":"https://api.harvestapp.com/v2/projects/14308069/task_assignments?page=1&per_page=2000"
376 |   }
377 | }
378 | Retrieve a task assignment⚭
379 | 
380 | Retrieves the task assignment with the given ID. Returns a task assignment object and a 200 OK response code if a valid identifier was provided.
381 | 
382 | GET /v2/projects/{PROJECT_ID}/task_assignments/{TASK_ASSIGNMENT_ID}
383 | Example Request:
384 | 
385 | curl "https://api.harvestapp.com/v2/projects/14308069/task_assignments/155505016" \
386 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
387 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
388 |   -H "User-Agent: MyApp ([email protected])"
389 | Example Response:
390 | 
391 | {
392 |   "id":155505016,
393 |   "billable":false,
394 |   "is_active":true,
395 |   "created_at":"2017-06-26T21:52:18Z",
396 |   "updated_at":"2017-06-26T21:54:06Z",
397 |   "hourly_rate":100.0,
398 |   "budget":null,
399 |   "project":{
400 |     "id":14308069,
401 |     "name":"Online Store - Phase 1",
402 |     "code":"OS1"
403 |   },
404 |   "task":{
405 |     "id":8083369,
406 |     "name":"Research"
407 |   }
408 | }
409 | Create a task assignment⚭
410 | 
411 | Creates a new task assignment object. Returns a task assignment object and a 201 Created response code if the call succeeded.
412 | 
413 | POST /v2/projects/{PROJECT_ID}/task_assignments
414 | Parameter	Type	Required	Description
415 | task_id	integer	required	The ID of the task to associate with the project.
416 | is_active	boolean	optional	Whether the task assignment is active or archived. Defaults to true.
417 | billable	boolean	optional	Whether the task assignment is billable or not. Defaults to false.
418 | hourly_rate	decimal	optional	Rate used when the project’s bill_by is Tasks. Defaults to null when billing by task hourly rate, otherwise 0.
419 | budget	decimal	optional	Budget used when the project’s budget_by is task or task_fees.
420 | Example Request:
421 | 
422 | curl "https://api.harvestapp.com/v2/projects/14308069/task_assignments" \
423 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
424 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
425 |   -H "User-Agent: MyApp ([email protected])" \
426 |   -X POST \
427 |   -H "Content-Type: application/json" \
428 |   -d '{"task_id":8083800,"is_active":true,"billable":true,"hourly_rate":75.50}'
429 | Example Response:
430 | 
431 | {
432 |   "id":155506339,
433 |   "billable":true,
434 |   "is_active":true,
435 |   "created_at":"2017-06-26T22:10:43Z",
436 |   "updated_at":"2017-06-26T22:10:43Z",
437 |   "hourly_rate":75.5,
438 |   "budget":null,
439 |   "project":{
440 |     "id":14308069,
441 |     "name":"Online Store - Phase 1",
442 |     "code":"OS1"
443 |   },
444 |   "task":{
445 |     "id":8083800,
446 |     "name":"Business Development"
447 |   }
448 | }
449 | Update a task assignment⚭
450 | 
451 | Updates the specific task assignment by setting the values of the parameters passed. Any parameters not provided will be left unchanged. Returns a task assignment object and a 200 OK response code if the call succeeded.
452 | 
453 | PATCH /v2/projects/{PROJECT_ID}/task_assignments/{TASK_ASSIGNMENT_ID}
454 | Parameter	Type	Description
455 | is_active	boolean	Whether the task assignment is active or archived.
456 | billable	boolean	Whether the task assignment is billable or not.
457 | hourly_rate	decimal	Rate used when the project’s bill_by is Tasks.
458 | budget	decimal	Budget used when the project’s budget_by is task or task_fees.
459 | Example Request:
460 | 
461 | curl "https://api.harvestapp.com/v2/projects/14308069/task_assignments/155506339" \
462 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
463 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
464 |   -H "User-Agent: MyApp ([email protected])" \
465 |   -X PATCH \
466 |   -H "Content-Type: application/json" \
467 |   -d '{"budget":120}'
468 | Example Response:
469 | 
470 | {
471 |   "id":155506339,
472 |   "billable":true,
473 |   "is_active":true,
474 |   "created_at":"2017-06-26T22:10:43Z",
475 |   "updated_at":"2017-06-26T22:11:27Z",
476 |   "hourly_rate":75.5,
477 |   "budget":120.0,
478 |   "project":{
479 |     "id":14308069,
480 |     "name":"Online Store - Phase 1",
481 |     "code":"OS1"
482 |   },
483 |   "task":{
484 |     "id":8083800,
485 |     "name":"Business Development"
486 |   }
487 | }
488 | Delete a task assignment⚭
489 | 
490 | Delete a task assignment. Deleting a task assignment is only possible if it has no time entries associated with it. Returns a 200 OK response code if the call succeeded.
491 | 
492 | DELETE /v2/projects/{PROJECT_ID}/task_assignments/{TASK_ASSIGNMENT_ID}
493 | Example Request:
494 | 
495 | curl "https://api.harvestapp.com/v2/projects/14308069/task_assignments/155506339" \
496 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
497 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
498 |   -H "User-Agent: MyApp ([email protected])" \
499 |   -X DELETE
500 | 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
  1 | #!/usr/bin/env node
  2 | import { Server } from '@modelcontextprotocol/sdk/server/index.js';
  3 | import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
  4 | import {
  5 |   CallToolRequestSchema,
  6 |   ErrorCode,
  7 |   ListToolsRequestSchema,
  8 |   McpError,
  9 | } from '@modelcontextprotocol/sdk/types.js';
 10 | import axios from 'axios';
 11 | import * as chrono from 'chrono-node';
 12 | 
 13 | // Time report response types
 14 | interface TimeReportResult {
 15 |   client_id?: number;
 16 |   client_name?: string;
 17 |   project_id?: number;
 18 |   project_name?: string;
 19 |   task_id?: number;
 20 |   task_name?: string;
 21 |   user_id?: number;
 22 |   user_name?: string;
 23 |   weekly_capacity?: number;
 24 |   avatar_url?: string;
 25 |   is_contractor?: boolean;
 26 |   total_hours: number;
 27 |   billable_hours: number;
 28 |   currency: string;
 29 |   billable_amount: number;
 30 | }
 31 | 
 32 | interface TimeReportResponse {
 33 |   results: TimeReportResult[];
 34 |   per_page: number;
 35 |   total_pages: number;
 36 |   total_entries: number;
 37 |   next_page: number | null;
 38 |   previous_page: number | null;
 39 |   page: number;
 40 | }
 41 | 
 42 | const HARVEST_ACCESS_TOKEN = process.env.HARVEST_ACCESS_TOKEN;
 43 | const HARVEST_ACCOUNT_ID = process.env.HARVEST_ACCOUNT_ID;
 44 | const STANDARD_WORK_DAY_HOURS = parseFloat(process.env.STANDARD_WORK_DAY_HOURS || '7.5');
 45 | const TIMEZONE = process.env.TIMEZONE || 'Australia/Perth';
 46 | 
 47 | if (!HARVEST_ACCESS_TOKEN || !HARVEST_ACCOUNT_ID) {
 48 |   throw new Error('HARVEST_ACCESS_TOKEN and HARVEST_ACCOUNT_ID environment variables are required');
 49 | }
 50 | 
 51 | // Special patterns for leave requests
 52 | const LEAVE_PATTERNS = {
 53 |   sick: {
 54 |     triggers: ['sick', 'ill', 'unwell'],
 55 |     project: '[LV] Leave',
 56 |     task: "Person (Sick/Carer's) Leave",
 57 |   },
 58 |   annual: {
 59 |     triggers: ['annual leave', 'vacation', 'holiday', 'time off'],
 60 |     project: '[LV] Leave',
 61 |     task: 'Annual Leave',
 62 |   }
 63 | };
 64 | 
 65 | class HarvestServer {
 66 |   private server: Server;
 67 |   private axiosInstance;
 68 | 
 69 |   constructor() {
 70 |     this.server = new Server(
 71 |       {
 72 |         name: 'harvest-server',
 73 |         version: '0.1.0',
 74 |       },
 75 |       {
 76 |         capabilities: {
 77 |           tools: {},
 78 |         },
 79 |       }
 80 |     );
 81 | 
 82 |     this.axiosInstance = axios.create({
 83 |       baseURL: 'https://api.harvestapp.com/v2',
 84 |       headers: {
 85 |         'Authorization': `Bearer ${HARVEST_ACCESS_TOKEN}`,
 86 |         'Harvest-Account-Id': HARVEST_ACCOUNT_ID,
 87 |         'User-Agent': 'Harvest MCP Server ([email protected])',
 88 |       },
 89 |     });
 90 | 
 91 |     this.setupToolHandlers();
 92 |     
 93 |     this.server.onerror = (error) => console.error('[MCP Error]', error);
 94 |     process.on('SIGINT', async () => {
 95 |       await this.server.close();
 96 |       process.exit(0);
 97 |     });
 98 |   }
 99 | 
100 |   private isLeaveRequest(text: string): { isLeave: boolean; type?: keyof typeof LEAVE_PATTERNS } {
101 |     const lowercaseText = text.toLowerCase();
102 |     for (const [type, pattern] of Object.entries(LEAVE_PATTERNS)) {
103 |       if (pattern.triggers.some(trigger => lowercaseText.includes(trigger))) {
104 |         return { isLeave: true, type: type as keyof typeof LEAVE_PATTERNS };
105 |       }
106 |     }
107 |     return { isLeave: false };
108 |   }
109 | 
110 |   private parseDateRange(text: string): { from: string; to: string } {
111 |     const lowercaseText = text.toLowerCase();
112 |     const now = new Date(new Date().toLocaleString('en-US', { timeZone: TIMEZONE }));
113 |     
114 |     // Handle common time ranges
115 |     if (lowercaseText.includes('last month')) {
116 |       const from = new Date(now.getFullYear(), now.getMonth() - 1, 1);
117 |       const to = new Date(now.getFullYear(), now.getMonth(), 0);
118 |       return {
119 |         from: from.toISOString().split('T')[0],
120 |         to: to.toISOString().split('T')[0]
121 |       };
122 |     }
123 |     
124 |     if (lowercaseText.includes('this month')) {
125 |       const from = new Date(now.getFullYear(), now.getMonth(), 1);
126 |       const to = now;
127 |       return {
128 |         from: from.toISOString().split('T')[0],
129 |         to: to.toISOString().split('T')[0]
130 |       };
131 |     }
132 |     
133 |     if (lowercaseText.includes('this week')) {
134 |       const from = new Date(now);
135 |       from.setDate(now.getDate() - now.getDay());
136 |       return {
137 |         from: from.toISOString().split('T')[0],
138 |         to: now.toISOString().split('T')[0]
139 |       };
140 |     }
141 | 
142 |     if (lowercaseText.includes('last week')) {
143 |       const from = new Date(now);
144 |       from.setDate(now.getDate() - now.getDay() - 7);
145 |       const to = new Date(from);
146 |       to.setDate(from.getDate() + 6);
147 |       return {
148 |         from: from.toISOString().split('T')[0],
149 |         to: to.toISOString().split('T')[0]
150 |       };
151 |     }
152 | 
153 |     // Default to parsing with chrono
154 |     const dates = chrono.parse(text);
155 |     if (dates.length === 0) {
156 |       throw new McpError(ErrorCode.InvalidParams, 'Could not parse date range from input');
157 |     }
158 | 
159 |     return {
160 |       from: dates[0].start.date().toISOString().split('T')[0],
161 |       to: (dates[0].end?.date() || dates[0].start.date()).toISOString().split('T')[0]
162 |     };
163 |   }
164 | 
165 |   private async parseTimeEntry(text: string) {
166 |     const lowercaseText = text.toLowerCase();
167 |     const now = new Date(new Date().toLocaleString('en-US', { timeZone: TIMEZONE }));
168 |     
169 |     // Check if this is a leave request
170 |     const leaveCheck = this.isLeaveRequest(text);
171 |     if (leaveCheck.isLeave && leaveCheck.type) {
172 |       // For leave requests, use the full work day
173 |       return {
174 |         spent_date: now.toISOString().split('T')[0],
175 |         hours: STANDARD_WORK_DAY_HOURS,
176 |         isLeave: true,
177 |         leaveType: leaveCheck.type
178 |       };
179 |     }
180 | 
181 |     // For regular time entries
182 |     let date: Date;
183 |     if (lowercaseText.includes('today')) {
184 |       date = now;
185 |     } else {
186 |       const parsed = chrono.parseDate(text);
187 |       if (!parsed) {
188 |         throw new McpError(ErrorCode.InvalidParams, 'Could not parse date from input');
189 |       }
190 |       date = parsed;
191 |     }
192 | 
193 |     // Extract hours/minutes
194 |     const durationMatch = text.match(/(\d+)\s*(hour|hr|h|minute|min|m)s?/i);
195 |     if (!durationMatch) {
196 |       throw new McpError(ErrorCode.InvalidParams, 'Could not parse duration from input');
197 |     }
198 | 
199 |     const amount = parseInt(durationMatch[1]);
200 |     const unit = durationMatch[2].toLowerCase();
201 |     const hours = unit.startsWith('h') ? amount : amount / 60;
202 | 
203 |     return {
204 |       spent_date: date.toISOString().split('T')[0],
205 |       hours,
206 |       isLeave: false
207 |     };
208 |   }
209 | 
210 |   private async findProject(text: string, isLeave: boolean = false, leaveType?: keyof typeof LEAVE_PATTERNS): Promise<number> {
211 |     const response = await this.axiosInstance.get('/projects');
212 |     const projects = response.data.projects;
213 |     
214 |     if (isLeave && leaveType) {
215 |       // For leave requests, look for the specific leave project
216 |       const leaveProject = projects.find((p: { name: string; id: number }) => 
217 |         p.name === LEAVE_PATTERNS[leaveType].project
218 |       );
219 |       if (leaveProject) {
220 |         return leaveProject.id;
221 |       }
222 |     }
223 |     
224 |     // For regular entries or if leave project not found
225 |     const projectMatch = projects.find((p: { name: string; id: number }) => 
226 |       text.toLowerCase().includes(p.name.toLowerCase())
227 |     );
228 | 
229 |     if (!projectMatch) {
230 |       throw new McpError(ErrorCode.InvalidParams, 'Could not find matching project');
231 |     }
232 | 
233 |     return projectMatch.id;
234 |   }
235 | 
236 |   private async findTask(projectId: number, text: string, isLeave: boolean = false, leaveType?: keyof typeof LEAVE_PATTERNS): Promise<number> {
237 |     const response = await this.axiosInstance.get(`/projects/${projectId}/task_assignments`);
238 |     const tasks = response.data.task_assignments;
239 | 
240 |     if (isLeave && leaveType) {
241 |       // For leave requests, look for the specific leave task
242 |       const leaveTask = tasks.find((t: { task: { name: string; id: number } }) => 
243 |         t.task.name === LEAVE_PATTERNS[leaveType].task
244 |       );
245 |       if (leaveTask) {
246 |         return leaveTask.task.id;
247 |       }
248 |     }
249 | 
250 |     // For regular entries or if leave task not found
251 |     const taskMatch = tasks.find((t: { task: { name: string; id: number } }) => 
252 |       text.toLowerCase().includes(t.task.name.toLowerCase())
253 |     );
254 | 
255 |     if (!taskMatch) {
256 |       // Default to first task if no match found
257 |       return tasks[0].task.id;
258 |     }
259 | 
260 |     return taskMatch.task.id;
261 |   }
262 | 
263 |   private setupToolHandlers() {
264 |     this.server.setRequestHandler(ListToolsRequestSchema, async () => ({
265 |       tools: [
266 |         {
267 |           name: 'log_time',
268 |           description: 'Log time entry using natural language',
269 |           inputSchema: {
270 |             type: 'object',
271 |             properties: {
272 |               text: {
273 |                 type: 'string',
274 |                 description: 'Natural language time entry (e.g. "2 hours on Project X doing development work yesterday")',
275 |               },
276 |             },
277 |             required: ['text'],
278 |           },
279 |         },
280 |         {
281 |           name: 'list_projects',
282 |           description: 'List available Harvest projects',
283 |           inputSchema: {
284 |             type: 'object',
285 |             properties: {},
286 |           },
287 |         },
288 |         {
289 |           name: 'list_tasks',
290 |           description: 'List available tasks for a project',
291 |           inputSchema: {
292 |             type: 'object',
293 |             properties: {
294 |               project_id: {
295 |                 type: 'number',
296 |                 description: 'Project ID',
297 |               },
298 |             },
299 |             required: ['project_id'],
300 |           },
301 |         },
302 |         {
303 |           name: 'list_entries',
304 |           description: 'List recent time entries',
305 |           inputSchema: {
306 |             type: 'object',
307 |             properties: {
308 |               from: {
309 |                 type: 'string',
310 |                 description: 'Start date (YYYY-MM-DD)',
311 |               },
312 |               to: {
313 |                 type: 'string',
314 |                 description: 'End date (YYYY-MM-DD)',
315 |               },
316 |             },
317 |           },
318 |         },
319 |         {
320 |           name: 'get_time_report',
321 |           description: 'Get time reports using natural language',
322 |           inputSchema: {
323 |             type: 'object',
324 |             properties: {
325 |               text: {
326 |                 type: 'string',
327 |                 description: 'Natural language query (e.g., "Show time report for last month", "Get time summary for Project X")',
328 |               },
329 |             },
330 |             required: ['text'],
331 |           },
332 |         },
333 |       ],
334 |     }));
335 | 
336 |     this.server.setRequestHandler(CallToolRequestSchema, async (request) => {
337 |       switch (request.params.name) {
338 |         case 'log_time': {
339 |           const { text } = request.params.arguments as { text: string };
340 |           
341 |           try {
342 |             // Parse time entry details
343 |             const { spent_date, hours, isLeave, leaveType } = await this.parseTimeEntry(text);
344 |             
345 |             // Find matching project
346 |             const project_id = await this.findProject(text, isLeave, leaveType);
347 |             
348 |             // Find matching task
349 |             const task_id = await this.findTask(project_id, text, isLeave, leaveType);
350 |             
351 |             // Create time entry
352 |             const response = await this.axiosInstance.post('/time_entries', {
353 |               project_id,
354 |               task_id,
355 |               spent_date,
356 |               hours,
357 |               notes: text,
358 |             });
359 | 
360 |             return {
361 |               content: [
362 |                 {
363 |                   type: 'text',
364 |                   text: JSON.stringify(response.data, null, 2),
365 |                 },
366 |               ],
367 |             };
368 |           } catch (error) {
369 |             if (error instanceof McpError) {
370 |               throw error;
371 |             }
372 |             if (axios.isAxiosError(error)) {
373 |               throw new McpError(
374 |                 ErrorCode.InternalError,
375 |                 `Harvest API error: ${error.response?.data?.message ?? error.message}`
376 |               );
377 |             }
378 |             throw error;
379 |           }
380 |         }
381 | 
382 |         case 'list_projects': {
383 |           const response = await this.axiosInstance.get('/projects');
384 |           return {
385 |             content: [
386 |               {
387 |                 type: 'text',
388 |                 text: JSON.stringify(response.data.projects.map((p: { id: number; name: string; code: string; is_active: boolean }) => ({
389 |                   id: p.id,
390 |                   name: p.name,
391 |                   code: p.code,
392 |                   is_active: p.is_active,
393 |                 })), null, 2),
394 |               },
395 |             ],
396 |           };
397 |         }
398 | 
399 |         case 'list_tasks': {
400 |           const { project_id } = request.params.arguments as { project_id: number };
401 |           const response = await this.axiosInstance.get(`/projects/${project_id}/task_assignments`);
402 |           return {
403 |             content: [
404 |               {
405 |                 type: 'text',
406 |                 text: JSON.stringify(response.data.task_assignments.map((t: { task: { id: number; name: string } }) => ({
407 |                   id: t.task.id,
408 |                   name: t.task.name,
409 |                 })), null, 2),
410 |               },
411 |             ],
412 |           };
413 |         }
414 | 
415 |         case 'list_entries': {
416 |           const { from, to } = request.params.arguments as { from?: string; to?: string };
417 |           const params: Record<string, string> = {};
418 |           if (from) params.from = from;
419 |           if (to) params.to = to;
420 |           
421 |           const response = await this.axiosInstance.get('/time_entries', { params });
422 |           return {
423 |             content: [
424 |               {
425 |                 type: 'text',
426 |                 text: JSON.stringify(response.data.time_entries.map((e: { id: number; spent_date: string; hours: number; notes: string; project: { name: string }; task: { name: string } }) => ({
427 |                   id: e.id,
428 |                   spent_date: e.spent_date,
429 |                   hours: e.hours,
430 |                   notes: e.notes,
431 |                   project: e.project.name,
432 |                   task: e.task.name,
433 |                 })), null, 2),
434 |               },
435 |             ],
436 |           };
437 |         }
438 | 
439 |         case 'get_time_report': {
440 |           const { text } = request.params.arguments as { text: string };
441 |           
442 |           try {
443 |             const { from, to } = this.parseDateRange(text);
444 |             const lowercaseText = text.toLowerCase();
445 |             
446 |             let endpoint = '/reports/time/projects'; // default to project report
447 |             
448 |             if (lowercaseText.includes('by client') || lowercaseText.includes('for client')) {
449 |               endpoint = '/reports/time/clients';
450 |             } else if (lowercaseText.includes('by task') || lowercaseText.includes('tasks')) {
451 |               endpoint = '/reports/time/tasks';
452 |             } else if (lowercaseText.includes('by team') || lowercaseText.includes('by user')) {
453 |               endpoint = '/reports/time/team';
454 |             }
455 |             
456 |             const response = await this.axiosInstance.get<TimeReportResponse>(endpoint, {
457 |               params: { from, to }
458 |             });
459 | 
460 |             return {
461 |               content: [
462 |                 {
463 |                   type: 'text',
464 |                   text: JSON.stringify(response.data, null, 2),
465 |                 },
466 |               ],
467 |             };
468 |           } catch (error) {
469 |             if (error instanceof McpError) {
470 |               throw error;
471 |             }
472 |             if (axios.isAxiosError(error)) {
473 |               throw new McpError(
474 |                 ErrorCode.InternalError,
475 |                 `Harvest API error: ${error.response?.data?.message ?? error.message}`
476 |               );
477 |             }
478 |             throw error;
479 |           }
480 |         }
481 | 
482 |         default:
483 |           throw new McpError(
484 |             ErrorCode.MethodNotFound,
485 |             `Unknown tool: ${request.params.name}`
486 |           );
487 |       }
488 |     });
489 |   }
490 | 
491 |   async run() {
492 |     const transport = new StdioServerTransport();
493 |     await this.server.connect(transport);
494 |     console.error('Harvest MCP server running on stdio');
495 |   }
496 | }
497 | 
498 | const server = new HarvestServer();
499 | server.run().catch(console.error);
500 | 
```

--------------------------------------------------------------------------------
/docs/harvest_api_docs/12_users/users.md:
--------------------------------------------------------------------------------

```markdown
  1 | Users
  2 | 
  3 | The user object⚭
  4 | 
  5 | Attribute	Type	Description
  6 | id	integer	Unique ID for the user.
  7 | first_name	string	The first name of the user.
  8 | last_name	string	The last name of the user.
  9 | email	string	The email address of the user.
 10 | telephone	string	The user’s telephone number.
 11 | timezone	string	The user’s timezone.
 12 | has_access_to_all_future_projects	boolean	Whether the user should be automatically added to future projects.
 13 | is_contractor	boolean	Whether the user is a contractor or an employee.
 14 | is_active	boolean	Whether the user is active or archived.
 15 | weekly_capacity	integer	The number of hours per week this person is available to work in seconds, in half hour increments. For example, if a person’s capacity is 35 hours, the API will return 126000 seconds.
 16 | default_hourly_rate	decimal	The billable rate to use for this user when they are added to a project.
 17 | cost_rate	decimal	The cost rate to use for this user when calculating a project’s costs vs billable amount.
 18 | roles	array of strings	Descriptive names of the business roles assigned to this person. They can be used for filtering reports, and have no effect in their permissions in Harvest.
 19 | access_roles	array of strings	Access role(s) that determine the user’s permissions in Harvest. Possible values: administrator, manager or member. Users with the manager role can additionally be granted one or more of these roles: project_creator, billable_rates_manager, managed_projects_invoice_drafter, managed_projects_invoice_manager, client_and_task_manager, time_and_expenses_manager, estimates_manager.
 20 | avatar_url	string	The URL to the user’s avatar image.
 21 | created_at	datetime	Date and time the user was created.
 22 | updated_at	datetime	Date and time the user was last updated.
 23 | Required permissions⚭
 24 | 
 25 | You must be an Administrator or Manager with assigned teammates in order to interact with the /v2/users endpoint, except when retrieving the currently authenticated user. Managers cannot edit emails, roles, or permissions, nor can they archive, restore, or delete assigned temmates. Managers with permission to see billable rates will have access to their teammates’ default hourly rates. Insufficient permissions will result in a 403 Forbidden status code.
 26 | 
 27 | List all users⚭
 28 | 
 29 | Returns a list of your users. The users are returned sorted by creation date, with the most recently created users appearing first.
 30 | 
 31 | The response contains an object with a users property that contains an array of up to per_page users. Each entry in the array is a separate user object. If no more users are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your users.
 32 | 
 33 | GET /v2/users
 34 | Parameter	Type	Description
 35 | is_active	boolean	Pass true to only return active users and false to return inactive users.
 36 | updated_since	datetime	Only return users that have been updated since the given date and time.
 37 | page	integer	DEPRECATED The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)
 38 | per_page	integer	The number of records to return per page. Can range between 1 and 2000. (Default: 2000)
 39 | This endpoint supports cursor-based pagination and therefore deprecates the page parameter. For more information, visit the pagination guide.
 40 | Example requests:⚭
 41 | 
 42 | Curl
 43 | Postman
 44 |  
 45 | curl "https://api.harvestapp.com/v2/users" \
 46 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
 47 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
 48 |   -H "User-Agent: MyApp ([email protected])"
 49 | 
 50 | 
 51 | Copy to Clipboard
 52 | Example response:
 53 | 
 54 | {
 55 |   "users":[
 56 |     {
 57 |       "id":3230547,
 58 |       "first_name":"Jim",
 59 |       "last_name":"Allen",
 60 |       "email":"[email protected]",
 61 |       "telephone":"",
 62 |       "timezone":"Mountain Time (US & Canada)",
 63 |       "has_access_to_all_future_projects":false,
 64 |       "is_contractor":false,
 65 |       "is_active":true,
 66 |       "created_at":"2020-05-01T22:34:41Z",
 67 |       "updated_at":"2020-05-01T22:34:52Z",
 68 |       "weekly_capacity":126000,
 69 |       "default_hourly_rate":100.0,
 70 |       "cost_rate":50.0,
 71 |       "roles":["Developer"],
 72 |       "access_roles": ["member"],
 73 |       "avatar_url":"https://cache.harvestapp.com/assets/profile_images/abraj_albait_towers.png?1498516481"
 74 |     },
 75 |     {
 76 |       "id":1782959,
 77 |       "first_name":"Kim",
 78 |       "last_name":"Allen",
 79 |       "email":"[email protected]",
 80 |       "telephone":"",
 81 |       "timezone":"Eastern Time (US & Canada)",
 82 |       "has_access_to_all_future_projects":true,
 83 |       "is_contractor":false,
 84 |       "is_active":true,
 85 |       "created_at":"2020-05-01T22:15:45Z",
 86 |       "updated_at":"2020-05-01T22:32:52Z",
 87 |       "weekly_capacity":126000,
 88 |       "default_hourly_rate":100.0,
 89 |       "cost_rate":50.0,
 90 |       "roles":["Designer"],
 91 |       "access_roles": ["member"],
 92 |       "avatar_url":"https://cache.harvestapp.com/assets/profile_images/cornell_clock_tower.png?1498515345"
 93 |     },
 94 |     {
 95 |       "id":1782884,
 96 |       "first_name":"Bob",
 97 |       "last_name":"Powell",
 98 |       "email":"[email protected]",
 99 |       "telephone":"",
100 |       "timezone":"Mountain Time (US & Canada)",
101 |       "has_access_to_all_future_projects":false,
102 |       "is_contractor":false,
103 |       "is_active":true,
104 |       "created_at":"2020-05-01T20:41:00Z",
105 |       "updated_at":"2020-05-01T20:42:25Z",
106 |       "weekly_capacity":126000,
107 |       "default_hourly_rate":100.0,
108 |       "cost_rate":75.0,
109 |       "roles":["Founder", "CEO"],
110 |       "access_roles": ["administrator"],
111 |       "avatar_url":"https://cache.harvestapp.com/assets/profile_images/allen_bradley_clock_tower.png?1498509661"
112 |     }
113 |   ],
114 |   "per_page":2000,
115 |   "total_pages":1,
116 |   "total_entries":3,
117 |   "next_page":null,
118 |   "previous_page":null,
119 |   "page":1,
120 |   "links":{
121 |     "first":"https://api.harvestapp.com/v2/users?page=1&per_page=2000",
122 |     "next":null,
123 |     "previous":null,
124 |     "last":"https://api.harvestapp.com/v2/users?page=1&per_page=2000"
125 |   }
126 | }
127 | Retrieve the currently authenticated user⚭
128 | 
129 | Retrieves the currently authenticated user. Returns a user object and a 200 OK response code.
130 | 
131 | GET /v2/users/me
132 | Example requests:⚭
133 | 
134 | Curl
135 | Postman
136 |  
137 | curl "https://api.harvestapp.com/v2/users/me" \
138 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
139 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
140 |   -H "User-Agent: MyApp ([email protected])"
141 | 
142 | 
143 | Copy to Clipboard
144 | Example response:⚭
145 | 
146 | {
147 |   "id":1782884,
148 |   "first_name":"Bob",
149 |   "last_name":"Powell",
150 |   "email":"[email protected]",
151 |   "telephone":"",
152 |   "timezone":"Mountain Time (US & Canada)",
153 |   "has_access_to_all_future_projects":false,
154 |   "is_contractor":false,
155 |   "is_active":true,
156 |   "created_at":"2020-05-01T20:41:00Z",
157 |   "updated_at":"2020-05-01T20:42:25Z",
158 |   "weekly_capacity":126000,
159 |   "default_hourly_rate":100.0,
160 |   "cost_rate":75.0,
161 |   "roles":["Founder", "CEO"],
162 |   "access_roles": ["administrator"],
163 |   "avatar_url":"https://cache.harvestapp.com/assets/profile_images/allen_bradley_clock_tower.png?1498509661"
164 | }
165 | Retrieve a user⚭
166 | 
167 | Retrieves the user with the given ID. Returns a user object and a 200 OK response code if a valid identifier was provided.
168 | 
169 | GET /v2/users/{USER_ID}
170 | Example requests:⚭
171 | 
172 | Curl
173 | Postman
174 |  
175 | curl "https://api.harvestapp.com/v2/users/3230547" \
176 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
177 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
178 |   -H "User-Agent: MyApp ([email protected])"
179 | 
180 | 
181 | Copy to Clipboard
182 | Example response:⚭
183 | 
184 | {
185 |   "id":3230547,
186 |   "first_name":"Jim",
187 |   "last_name":"Allen",
188 |   "email":"[email protected]",
189 |   "telephone":"",
190 |   "timezone":"Mountain Time (US & Canada)",
191 |   "has_access_to_all_future_projects":false,
192 |   "is_contractor":false,
193 |   "is_active":true,
194 |   "created_at":"2020-05-01T22:34:41Z",
195 |   "updated_at":"2020-05-01T22:34:52Z",
196 |   "weekly_capacity":126000,
197 |   "default_hourly_rate":100.0,
198 |   "cost_rate":50.0,
199 |   "roles":["Developer"],
200 |   "access_roles": ["member"],
201 |   "avatar_url":"https://cache.harvestapp.com/assets/profile_images/abraj_albait_towers.png?1498516481"
202 | }
203 | Create a user⚭
204 | 
205 | Creates a new user object and sends an invitation email to the address specified in the email parameter. Returns a user object and a 201 Created response code if the call succeeded.
206 | 
207 | POST /v2/users
208 | Parameter	Type	Required	Description
209 | first_name	string	required	The first name of the user.
210 | last_name	string	required	The last name of the user.
211 | email	string	required	The email address of the user.
212 | timezone	string	optional	The user’s timezone. Defaults to the company’s timezone. See a list of supported time zones.
213 | has_access_to_all_future_projects	boolean	optional	Whether the user should be automatically added to future projects. Defaults to false.
214 | is_contractor	boolean	optional	Whether the user is a contractor or an employee. Defaults to false.
215 | is_active	boolean	optional	Whether the user is active or archived. Defaults to true.
216 | weekly_capacity	integer	optional	The number of hours per week this person is available to work in seconds. Defaults to 126000 seconds (35 hours).
217 | default_hourly_rate	decimal	optional	The billable rate to use for this user when they are added to a project. Defaults to 0.
218 | cost_rate	decimal	optional	The cost rate to use for this user when calculating a project’s costs vs billable amount. Defaults to 0.
219 | roles	array of strings	optional	Descriptive names of the business roles assigned to this person. They can be used for filtering reports, and have no effect in their permissions in Harvest.
220 | access_roles	array of strings	optional	Access role(s) that determine the user’s permissions in Harvest. Possible values: administrator, manager or member. Users with the manager role can additionally be granted one or more of these roles: project_creator, billable_rates_manager, managed_projects_invoice_drafter, managed_projects_invoice_manager, client_and_task_manager, time_and_expenses_manager, estimates_manager.
221 | Access Roles⚭
222 | 
223 | To set permissions for a user, use the access_roles parameter. A user must be one of the following: member, manager, or administrator.
224 | 
225 | If no access_role parameter is sent, a user defaults to ‘member’.
226 | If a user is a manager they can have other access roles set for more specific permissions in Harvest.
227 | The role of people_manager is determined by whether the user has teammates assigned to them, which can be added through the teammates api. If you downgrade a People Manager’s access role to Member, they will no longer be a People Manager and their assigned teammates will be removed.
228 | Access Role Name	Description
229 | administrator	For users who need the most control to manage your account. Administrators can see and do everything.
230 | manager	For users who need more access to people and project reports. Managers can track time and expenses, and edit, approve, and run reports for all time and expenses tracked to selected projects and people.
231 | member	For users who just need to track time and expenses.
232 | Additional Manager Access Role Names	Description
233 | project_creator	User can create projects, and edit projects that they manage.
234 | billable_rates_manager	User can see billable rates and amounts for projects and people they manage.
235 | managed_projects_invoice_drafter	User can create and edit draft invoices for projects they manage.
236 | managed_projects_invoice_manager	User can send and fully manage all invoices for projects they manage (record payments, edit non-drafts, send reminders and thank-yous, delete, etc).
237 | client_and_task_manager	User can create and edit all clients and tasks on the account.
238 | time_and_expenses_manager	User can create and edit time and expenses for people and projects they manage.
239 | estimates_manager	User can create and edit all estimates on the account.
240 | Learn more about team permissions
241 | 
242 | Example requests:⚭
243 | 
244 | Curl
245 | Postman
246 |  
247 | curl "https://api.harvestapp.com/v2/users" \
248 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
249 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
250 |   -H "User-Agent: MyApp ([email protected])" \
251 |   -X POST \
252 |   -H "Content-Type: application/json" \
253 |   -d '{"email":"[email protected]","first_name":"George","last_name":"Frank","access_roles":["manager","project_creator","time_and_expenses_manager"]}'
254 | 
255 | 
256 | Copy to Clipboard
257 | Example response:⚭
258 | 
259 | {
260 |   "id": 3,
261 |   "first_name": "George",
262 |   "last_name": "Frank",
263 |   "email": "[email protected]",
264 |   "telephone": "",
265 |   "timezone": "Eastern Time (US & Canada)",
266 |   "has_access_to_all_future_projects": false,
267 |   "is_contractor": false,
268 |   "is_active": true,
269 |   "weekly_capacity":126000,
270 |   "default_hourly_rate": 0,
271 |   "cost_rate": 0,
272 |   "roles": [],
273 |   "access_roles": [
274 |     "manager",
275 |     "project_creator",
276 |     "time_and_expenses_manager"
277 |   ],
278 |   "avatar_url": "https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/assets/profile_images/big_ben.png?1485372046",
279 |   "created_at": "2020-01-25T19:20:46Z",
280 |   "updated_at": "2020-01-25T19:20:57Z"
281 | }
282 | Update a user⚭
283 | 
284 | Updates the specific user by setting the values of the parameters passed. Any parameters not provided will be left unchanged. Returns a user object and a 200 OK response code if the call succeeded.
285 | 
286 | PATCH /v2/users/{USER_ID}
287 | Parameter	Type	Description
288 | first_name	string	The first name of the user. Can’t be updated if the user is inactive.
289 | last_name	string	The last name of the user. Can’t be updated if the user is inactive.
290 | email	string	The email address of the user. Can’t be updated if the user is inactive.
291 | timezone	string	The user’s timezone. Defaults to the company’s timezone. See a list of supported time zones.
292 | has_access_to_all_future_projects	boolean	Whether the user should be automatically added to future projects.
293 | is_contractor	boolean	Whether the user is a contractor or an employee.
294 | is_active	boolean	Whether the user is active or archived.
295 | weekly_capacity	integer	The number of hours per week this person is available to work in seconds.
296 | roles	array of strings	Descriptive names of the business roles assigned to this person. They can be used for filtering reports, and have no effect in their permissions in Harvest.
297 | access_roles	array of strings	Access role(s) that determine the user’s permissions in Harvest. Possible values: administrator, manager or member. Users with the manager role can additionally be granted one or more of these roles: project_creator, billable_rates_manager, managed_projects_invoice_drafter, managed_projects_invoice_manager, client_and_task_manager, time_and_expenses_manager, estimates_manager.
298 | Example requests:⚭
299 | 
300 | Curl
301 | Postman
302 |  
303 | curl "https://api.harvestapp.com/v2/users/3237198" \
304 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
305 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
306 |   -H "User-Agent: MyApp ([email protected])" \
307 |   -X PATCH \
308 |   -H "Content-Type: application/json" \
309 |   -d '{"roles":["Product Team"], "access_roles":["manager", "time_and_expenses_manager", "billable_rates_manager"]}'
310 | 
311 | 
312 | Copy to Clipboard
313 | Example response:⚭
314 | 
315 | {
316 |   "id": 3237198,
317 |   "first_name": "Gary",
318 |   "last_name": "Brookes",
319 |   "email": "[email protected]",
320 |   "telephone": "",
321 |   "timezone": "Eastern Time (US & Canada)",
322 |   "has_access_to_all_future_projects": true,
323 |   "is_contractor": false,
324 |   "is_active": true,
325 |   "weekly_capacity":126000,
326 |   "default_hourly_rate": 120,
327 |   "cost_rate": 50,
328 |   "roles": ["Product Team"],
329 |   "access_roles": [
330 |     "manager",
331 |     "time_and_expenses_manager",
332 |     "billable_rates_manager"
333 |   ],
334 |   "avatar_url": "https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/assets/profile_images/big_ben.png?1485372046",
335 |   "created_at": "2018-01-01T19:20:46Z",
336 |   "updated_at": "2019-01-25T19:20:57Z"
337 | }
338 | Archive a user⚭
339 | 
340 | Archives a specific user by setting the value of is_active to false. To make a user active again, simply set is_active to true again. Returns the updated user object and a 200 OK response code if the call succeeded.
341 | 
342 | PATCH /v2/users/{USER_ID}
343 | Example requests:⚭
344 | 
345 | Curl
346 | Postman
347 |  
348 | curl "https://api.harvestapp.com/v2/users/3226125" \
349 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
350 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
351 |   -H "User-Agent: MyApp ([email protected])" \
352 |   -X PATCH \
353 |   -H "Content-Type: application/json" \
354 |   -d '{"is_active":false}'
355 | 
356 | 
357 | Copy to Clipboard
358 | Example response:⚭
359 | 
360 | {
361 |   "id": 3226125,
362 |   "first_name": "Rachel",
363 |   "last_name": "Halliday",
364 |   "email": "[email protected]",
365 |   "telephone": "",
366 |   "timezone": "Eastern Time (US & Canada)",
367 |   "has_access_to_all_future_projects": true,
368 |   "is_contractor": false,
369 |   "is_active": false,
370 |   "weekly_capacity":126000,
371 |   "default_hourly_rate": 120,
372 |   "cost_rate": 50,
373 |   "roles": ["Developer"],
374 |   "access_roles": ["member"],
375 |   "avatar_url": "https://{ACCOUNT_SUBDOMAIN}.harvestapp.com/assets/profile_images/big_ben.png?1485372046",
376 |   "created_at": "2018-01-01T19:20:46Z",
377 |   "updated_at": "2019-01-25T19:20:57Z"
378 | }
379 | Delete a user⚭
380 | 
381 | Delete a user. Deleting a user is only possible if they have no time entries or expenses associated with them. Returns a 200 OK response code if the call succeeded.
382 | 
383 | DELETE /v2/users/{USER_ID}
384 | Example requests:⚭
385 | 
386 | Curl
387 | Postman
388 |  
389 | curl "https://api.harvestapp.com/v2/users/3237198" \
390 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
391 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
392 |   -H "User-Agent: MyApp ([email protected])" \
393 |   -X DELETE
394 | 
395 | 
396 | Copy to Clipboard
397 | 
```

--------------------------------------------------------------------------------
/docs/harvest_api_docs/09_timesheets/time_entries.md:
--------------------------------------------------------------------------------

```markdown
  1 | Time Entries
  2 | 
  3 | The time entry object⚭
  4 | 
  5 | Attribute Type  Description
  6 | id  bigint  Unique ID for the time entry.
  7 | spent_date  date  Date of the time entry.
  8 | user  object  An object containing the id and name of the associated user.
  9 | user_assignment object  A user assignment object of the associated user.
 10 | client  object  An object containing the id and name of the associated client.
 11 | project object  An object containing the id and name of the associated project.
 12 | task  object  An object containing the id and name of the associated task.
 13 | task_assignment object  A task assignment object of the associated task.
 14 | external_reference  object  An object containing the id, group_id, account_id, permalink, service, and service_icon_url of the associated external reference.
 15 | invoice object  Once the time entry has been invoiced, this field will include the associated invoice’s id and number.
 16 | hours decimal Number of (decimal time) hours tracked in this time entry.
 17 | hours_without_timer decimal Number of (decimal time) hours already tracked in this time entry, before the timer was last started.
 18 | rounded_hours decimal Number of (decimal time) hours tracked in this time entry used in summary reports and invoices. This value is rounded according to the Time Rounding setting in your Preferences.
 19 | notes string  Notes attached to the time entry.
 20 | is_locked boolean Whether or not the time entry has been locked.
 21 | locked_reason string  Why the time entry has been locked.
 22 | is_closed boolean Whether or not the time entry has been approved via Timesheet Approval.
 23 | is_billed boolean Whether or not the time entry has been marked as invoiced.
 24 | timer_started_at  datetime  Date and time the running timer was started (if tracking by duration). Use the ISO 8601 Format. Returns null for stopped timers.
 25 | started_time  time  Time the time entry was started (if tracking by start/end times).
 26 | ended_time  time  Time the time entry was ended (if tracking by start/end times).
 27 | is_running  boolean Whether or not the time entry is currently running.
 28 | billable  boolean Whether or not the time entry is billable.
 29 | budgeted  boolean Whether or not the time entry counts towards the project budget.
 30 | billable_rate decimal The billable rate for the time entry.
 31 | cost_rate decimal The cost rate for the time entry.
 32 | created_at  datetime  Date and time the time entry was created. Use the ISO 8601 Format.
 33 | updated_at  datetime  Date and time the time entry was last updated. Use the ISO 8601 Format.
 34 | Required permissions⚭
 35 | 
 36 | Administrators can see all time entries for the account.
 37 | 
 38 | Managers can see time entries for themselves, assigned teammates, and time tracked to projects they manage. Additionally, Managers with permission to edit assigned teammates’ time entries can create, edit, and destroy time entries on their behalf.
 39 | 
 40 | Members can only see their own tracked time.
 41 | 
 42 | List all time entries⚭
 43 | 
 44 | Returns a list of time entries. The time entries are returned sorted by spent_date date. At this time, the sort option can’t be customized.
 45 | 
 46 | The response contains an object with a time_entries property that contains an array of up to per_page time entries. Each entry in the array is a separate time entry object. If no more time entries are available, the resulting array will be empty. Several additional pagination properties are included in the response to simplify paginating your time entries.
 47 | 
 48 | GET /v2/time_entries
 49 | Parameter Type  Description
 50 | user_id integer Only return time entries belonging to the user with the given ID.
 51 | client_id integer Only return time entries belonging to the client with the given ID.
 52 | project_id  integer Only return time entries belonging to the project with the given ID.
 53 | task_id integer Only return time entries belonging to the task with the given ID.
 54 | external_reference_id string  Only return time entries with the given external_reference ID.
 55 | is_billed boolean Pass true to only return time entries that have been invoiced and false to return time entries that have not been invoiced.
 56 | is_running  boolean Pass true to only return running time entries and false to return non-running time entries.
 57 | updated_since datetime  Only return time entries that have been updated since the given date and time. Use the ISO 8601 Format.
 58 | from  date  Only return time entries with a spent_date on or after the given date.
 59 | to  date  Only return time entries with a spent_date on or before the given date.
 60 | page  integer The page number to use in pagination. For instance, if you make a list request and receive 2000 records, your subsequent call can include page=2 to retrieve the next page of the list. (Default: 1)
 61 | per_page  integer The number of records to return per page. Can range between 1 and 2000. (Default: 2000)
 62 | Example Request:
 63 | 
 64 | curl "<https://api.harvestapp.com/v2/time_entries>" \
 65 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
 66 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
 67 |   -H "User-Agent: MyApp (<[email protected]>)"
 68 | Example Response:
 69 | 
 70 | {
 71 |   "time_entries":[
 72 |     {
 73 |       "id":636709355,
 74 |       "spent_date":"2017-03-02",
 75 |       "user":{
 76 |         "id":1782959,
 77 |         "name":"Kim Allen"
 78 |       },
 79 |       "client":{
 80 |         "id":5735774,
 81 |         "name":"ABC Corp"
 82 |       },
 83 |       "project":{
 84 |         "id":14307913,
 85 |         "name":"Marketing Website"
 86 |       },
 87 |       "task":{
 88 |         "id":8083365,
 89 |         "name":"Graphic Design"
 90 |       },
 91 |       "user_assignment":{
 92 |         "id":125068553,
 93 |         "is_project_manager":true,
 94 |         "is_active":true,
 95 |         "budget":null,
 96 |         "created_at":"2017-06-26T22:32:52Z",
 97 |         "updated_at":"2017-06-26T22:32:52Z",
 98 |         "hourly_rate":100.0
 99 |       },
100 |       "task_assignment":{
101 |         "id":155502709,
102 |         "billable":true,
103 |         "is_active":true,
104 |         "created_at":"2017-06-26T21:36:23Z",
105 |         "updated_at":"2017-06-26T21:36:23Z",
106 |         "hourly_rate":100.0,
107 |         "budget":null
108 |       },
109 |       "hours":2.11,
110 |       "hours_without_timer":2.11,
111 |       "rounded_hours": 2.25,
112 |       "notes":"Adding CSS styling",
113 |       "created_at":"2017-06-27T15:50:15Z",
114 |       "updated_at":"2017-06-27T16:47:14Z",
115 |       "is_locked":true,
116 |       "locked_reason":"Item Approved and Locked for this Time Period",
117 |       "is_closed":true,
118 |       "is_billed":false,
119 |       "timer_started_at":null,
120 |       "started_time":"3:00pm",
121 |       "ended_time":"5:00pm",
122 |       "is_running":false,
123 |       "invoice":null,
124 |       "external_reference":null,
125 |       "billable":true,
126 |       "budgeted":true,
127 |       "billable_rate":100.0,
128 |       "cost_rate":50.0
129 |     },
130 |     {
131 |       "id":636708723,
132 |       "spent_date":"2017-03-01",
133 |       "user":{
134 |         "id":1782959,
135 |         "name":"Kim Allen"
136 |       },
137 |       "client":{
138 |         "id":5735776,
139 |         "name":"123 Industries"
140 |       },
141 |       "project":{
142 |         "id":14308069,
143 |         "name":"Online Store - Phase 1"
144 |       },
145 |       "task":{
146 |         "id":8083366,
147 |         "name":"Programming"
148 |       },
149 |       "user_assignment":{
150 |         "id":125068554,
151 |         "is_project_manager":true,
152 |         "is_active":true,
153 |         "budget":null,
154 |         "created_at":"2017-06-26T22:32:52Z",
155 |         "updated_at":"2017-06-26T22:32:52Z",
156 |         "hourly_rate":100.0
157 |       },
158 |       "task_assignment":{
159 |         "id":155505014,
160 |         "billable":true,
161 |         "is_active":true,
162 |         "created_at":"2017-06-26T21:52:18Z",
163 |         "updated_at":"2017-06-26T21:52:18Z",
164 |         "hourly_rate":100.0,
165 |         "budget":null
166 |       },
167 |       "hours":1.35,
168 |       "hours_without_timer":1.35,
169 |       "rounded_hours":1.5,
170 |       "notes":"Importing products",
171 |       "created_at":"2017-06-27T15:49:28Z",
172 |       "updated_at":"2017-06-27T16:47:14Z",
173 |       "is_locked":true,
174 |       "locked_reason":"Item Invoiced and Approved and Locked for this Time Period",
175 |       "is_closed":true,
176 |       "is_billed":true,
177 |       "timer_started_at":null,
178 |       "started_time":"1:00pm",
179 |       "ended_time":"2:00pm",
180 |       "is_running":false,
181 |       "invoice":{
182 |         "id":13150403,
183 |         "number":"1001"
184 |       },
185 |       "external_reference":null,
186 |       "billable":true,
187 |       "budgeted":true,
188 |       "billable_rate":100.0,
189 |       "cost_rate":50.0
190 |     },
191 |     {
192 |       "id":636708574,
193 |       "spent_date":"2017-03-01",
194 |       "user":{
195 |         "id":1782959,
196 |         "name":"Kim Allen"
197 |       },
198 |       "client":{
199 |         "id":5735776,
200 |         "name":"123 Industries"
201 |       },
202 |       "project":{
203 |         "id":14308069,
204 |         "name":"Online Store - Phase 1"
205 |       },
206 |       "task":{
207 |         "id":8083369,
208 |         "name":"Research"
209 |       },
210 |       "user_assignment":{
211 |         "id":125068554,
212 |         "is_project_manager":true,
213 |         "is_active":true,
214 |         "budget":null,
215 |         "created_at":"2017-06-26T22:32:52Z",
216 |         "updated_at":"2017-06-26T22:32:52Z",
217 |         "hourly_rate":100.0
218 |       },
219 |       "task_assignment":{
220 |         "id":155505016,
221 |         "billable":false,
222 |         "is_active":true,
223 |         "created_at":"2017-06-26T21:52:18Z",
224 |         "updated_at":"2017-06-26T21:54:06Z",
225 |         "hourly_rate":100.0,
226 |         "budget":null
227 |       },
228 |       "hours":1.0,
229 |       "hours_without_timer":1.0,
230 |       "rounded_hours":1.0,
231 |       "notes":"Evaluating 3rd party libraries",
232 |       "created_at":"2017-06-27T15:49:17Z",
233 |       "updated_at":"2017-06-27T16:47:14Z",
234 |       "is_locked":true,
235 |       "locked_reason":"Item Approved and Locked for this Time Period",
236 |       "is_closed":true,
237 |       "is_billed":false,
238 |       "timer_started_at":null,
239 |       "started_time":"11:00am",
240 |       "ended_time":"12:00pm",
241 |       "is_running":false,
242 |       "invoice":null,
243 |       "external_reference":null,
244 |       "billable":false,
245 |       "budgeted":true,
246 |       "billable_rate":null,
247 |       "cost_rate":50.0
248 |     },
249 |     {
250 |       "id":636707831,
251 |       "spent_date":"2017-03-01",
252 |       "user":{
253 |         "id":1782959,
254 |         "name":"Kim Allen"
255 |       },
256 |       "client":{
257 |         "id":5735776,
258 |         "name":"123 Industries"
259 |       },
260 |       "project":{
261 |         "id":14308069,
262 |         "name":"Online Store - Phase 1"
263 |       },
264 |       "task":{
265 |         "id":8083368,
266 |         "name":"Project Management"
267 |       },
268 |       "user_assignment":{
269 |         "id":125068554,
270 |         "is_project_manager":true,
271 |         "is_active":true,
272 |         "budget":null,
273 |         "created_at":"2017-06-26T22:32:52Z",
274 |         "updated_at":"2017-06-26T22:32:52Z",
275 |         "hourly_rate":100.0
276 |       },
277 |       "task_assignment":{
278 |         "id":155505015,
279 |         "billable":true,
280 |         "is_active":true,
281 |         "created_at":"2017-06-26T21:52:18Z",
282 |         "updated_at":"2017-06-26T21:52:18Z",
283 |         "hourly_rate":100.0,
284 |         "budget":null
285 |       },
286 |       "hours":2.0,
287 |       "hours_without_timer":2.0,
288 |       "rounded_hours":2.0,
289 |       "notes":"Planning meetings",
290 |       "created_at":"2017-06-27T15:48:24Z",
291 |       "updated_at":"2017-06-27T16:47:14Z",
292 |       "is_locked":true,
293 |       "locked_reason":"Item Invoiced and Approved and Locked for this Time Period",
294 |       "is_closed":true,
295 |       "is_billed":true,
296 |       "timer_started_at":null,
297 |       "started_time":"9:00am",
298 |       "ended_time":"11:00am",
299 |       "is_running":false,
300 |       "invoice":{
301 |         "id":13150403,
302 |         "number":"1001"
303 |       },
304 |       "external_reference":null,
305 |       "billable":true,
306 |       "budgeted":true,
307 |       "billable_rate":100.0,
308 |       "cost_rate":50.0
309 |     }
310 |   ],
311 |   "per_page":2000,
312 |   "total_pages":1,
313 |   "total_entries":4,
314 |   "next_page":null,
315 |   "previous_page":null,
316 |   "page":1,
317 |   "links":{
318 |     "first":"<https://api.harvestapp.com/v2/time_entries?page=1&per_page=2000>",
319 |     "next":null,
320 |     "previous":null,
321 |     "last":"<https://api.harvestapp.com/v2/time_entries?page=1&per_page=2000>"
322 |   }
323 | }
324 | Retrieve a time entry⚭
325 | 
326 | Retrieves the time entry with the given ID. Returns a time entry object and a 200 OK response code if a valid identifier was provided.
327 | 
328 | GET /v2/time_entries/{TIME_ENTRY_ID}
329 | Example Request:
330 | 
331 | curl "<https://api.harvestapp.com/v2/time_entries/636708723>" \
332 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
333 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
334 |   -H "User-Agent: MyApp (<[email protected]>)"
335 | Example Response:
336 | 
337 | {
338 |   "id":636708723,
339 |   "spent_date":"2017-03-01",
340 |   "user":{
341 |     "id":1782959,
342 |     "name":"Kim Allen"
343 |   },
344 |   "client":{
345 |     "id":5735776,
346 |     "name":"123 Industries"
347 |   },
348 |   "project":{
349 |     "id":14308069,
350 |     "name":"Online Store - Phase 1"
351 |   },
352 |   "task":{
353 |     "id":8083366,
354 |     "name":"Programming"
355 |   },
356 |   "user_assignment":{
357 |     "id":125068554,
358 |     "is_project_manager":true,
359 |     "is_active":true,
360 |     "budget":null,
361 |     "created_at":"2017-06-26T22:32:52Z",
362 |     "updated_at":"2017-06-26T22:32:52Z",
363 |     "hourly_rate":100.0
364 |   },
365 |   "task_assignment":{
366 |     "id":155505014,
367 |     "billable":true,
368 |     "is_active":true,
369 |     "created_at":"2017-06-26T21:52:18Z",
370 |     "updated_at":"2017-06-26T21:52:18Z",
371 |     "hourly_rate":100.0,
372 |     "budget":null
373 |   },
374 |   "hours":1.0,
375 |   "hours_without_timer":1.0,
376 |   "rounded_hours":1.0,
377 |   "notes":"Importing products",
378 |   "created_at":"2017-06-27T15:49:28Z",
379 |   "updated_at":"2017-06-27T16:47:14Z",
380 |   "is_locked":true,
381 |   "locked_reason":"Item Invoiced and Approved and Locked for this Time Period",
382 |   "is_closed":true,
383 |   "is_billed":true,
384 |   "timer_started_at":null,
385 |   "started_time":"1:00pm",
386 |   "ended_time":"2:00pm",
387 |   "is_running":false,
388 |   "invoice":{
389 |     "id":13150403,
390 |     "number":"1001"
391 |   },
392 |   "external_reference":null,
393 |   "billable":true,
394 |   "budgeted":true,
395 |   "billable_rate":100.0,
396 |   "cost_rate":50.0
397 | }
398 | Create a time entry via duration⚭
399 | 
400 | Creates a new time entry object. Returns a time entry object and a 201 Created response code if the call succeeded.
401 | 
402 | You should only use this method to create time entries when your account is configured to track time via duration. You can verify this by visiting the Settings page in your Harvest account or by checking if wants_timestamp_timers is false in the Company API.
403 | 
404 | POST /v2/time_entries
405 | Parameter Type  Required  Description
406 | user_id integer optional  The ID of the user to associate with the time entry. Defaults to the currently authenticated user’s ID.
407 | project_id  integer required  The ID of the project to associate with the time entry.
408 | task_id integer required  The ID of the task to associate with the time entry.
409 | spent_date  date  required  The ISO 8601 formatted date the time entry was spent.
410 | hours decimal optional  The current amount of time tracked. If provided, the time entry will be created with the specified hours and is_running will be set to false. If not provided, hours will be set to 0.0 and is_running will be set to true.
411 | notes string  optional  Any notes to be associated with the time entry.
412 | external_reference  object  optional  An object containing the id, group_id, account_id, and permalink of the external reference.
413 | Example Request:
414 | 
415 | curl "<https://api.harvestapp.com/v2/time_entries>" \
416 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
417 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
418 |   -H "User-Agent: MyApp (<[email protected]>)" \
419 |   -X POST \
420 |   -H "Content-Type: application/json" \
421 |   -d '{"user_id":1782959,"project_id":14307913,"task_id":8083365,"spent_date":"2017-03-21","hours":1.0}'
422 | Example Response:
423 | 
424 | {
425 |   "id":636718192,
426 |   "spent_date":"2017-03-21",
427 |   "user":{
428 |     "id":1782959,
429 |     "name":"Kim Allen"
430 |   },
431 |   "client":{
432 |     "id":5735774,
433 |     "name":"ABC Corp"
434 |   },
435 |   "project":{
436 |     "id":14307913,
437 |     "name":"Marketing Website"
438 |   },
439 |   "task":{
440 |     "id":8083365,
441 |     "name":"Graphic Design"
442 |   },
443 |   "user_assignment":{
444 |     "id":125068553,
445 |     "is_project_manager":true,
446 |     "is_active":true,
447 |     "budget":null,
448 |     "created_at":"2017-06-26T22:32:52Z",
449 |     "updated_at":"2017-06-26T22:32:52Z",
450 |     "hourly_rate":100.0
451 |   },
452 |   "task_assignment":{
453 |     "id":155502709,
454 |     "billable":true,
455 |     "is_active":true,
456 |     "created_at":"2017-06-26T21:36:23Z",
457 |     "updated_at":"2017-06-26T21:36:23Z",
458 |     "hourly_rate":100.0,
459 |     "budget":null
460 |   },
461 |   "hours":1.0,
462 |   "rounded_hours":1.0,
463 |   "notes":null,
464 |   "created_at":"2017-06-27T16:01:23Z",
465 |   "updated_at":"2017-06-27T16:01:23Z",
466 |   "is_locked":false,
467 |   "locked_reason":null,
468 |   "is_closed":false,
469 |   "is_billed":false,
470 |   "timer_started_at":null,
471 |   "started_time":null,
472 |   "ended_time":null,
473 |   "is_running":false,
474 |   "invoice":null,
475 |   "external_reference": null,
476 |   "billable":true,
477 |   "budgeted":true,
478 |   "billable_rate":100.0,
479 |   "cost_rate":50.0
480 | }
481 | Create a time entry via start and end time⚭
482 | 
483 | Creates a new time entry object. Returns a time entry object and a 201 Created response code if the call succeeded.
484 | 
485 | You should only use this method to create time entries when your account is configured to track time via start and end time. You can verify this by visiting the Settings page in your Harvest account or by checking if wants_timestamp_timers is true in the Company API.
486 | 
487 | POST /v2/time_entries
488 | Parameter Type  Required  Description
489 | user_id integer optional  The ID of the user to associate with the time entry. Defaults to the currently authenticated user’s ID.
490 | project_id  integer required  The ID of the project to associate with the time entry.
491 | task_id integer required  The ID of the task to associate with the time entry.
492 | spent_date  date  required  The ISO 8601 formatted date the time entry was spent.
493 | started_time  time  optional  The time the entry started. Defaults to the current time. Example: “8:00am”.
494 | ended_time  time  optional  The time the entry ended. If provided, is_running will be set to false. If not provided, is_running will be set to true.
495 | notes string  optional  Any notes to be associated with the time entry.
496 | external_reference  object  optional  An object containing the id, group_id, account_id, and permalink of the external reference.
497 | Example Request:
498 | 
499 | curl "<https://api.harvestapp.com/v2/time_entries>" \
500 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
501 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
502 |   -H "User-Agent: MyApp (<[email protected]>)" \
503 |   -X POST \
504 |   -H "Content-Type: application/json" \
505 |   -d '{"user_id":1782959,"project_id":14307913,"task_id":8083365,"spent_date":"2017-03-21","started_time":"8:00am","ended_time":"9:00am"}'
506 | Example Response:
507 | 
508 | {
509 |   "id":636718192,
510 |   "spent_date":"2017-03-21",
511 |   "user":{
512 |     "id":1782959,
513 |     "name":"Kim Allen"
514 |   },
515 |   "client":{
516 |     "id":5735774,
517 |     "name":"ABC Corp"
518 |   },
519 |   "project":{
520 |     "id":14307913,
521 |     "name":"Marketing Website"
522 |   },
523 |   "task":{
524 |     "id":8083365,
525 |     "name":"Graphic Design"
526 |   },
527 |   "user_assignment":{
528 |     "id":125068553,
529 |     "is_project_manager":true,
530 |     "is_active":true,
531 |     "budget":null,
532 |     "created_at":"2017-06-26T22:32:52Z",
533 |     "updated_at":"2017-06-26T22:32:52Z",
534 |     "hourly_rate":100.0
535 |   },
536 |   "task_assignment":{
537 |     "id":155502709,
538 |     "billable":true,
539 |     "is_active":true,
540 |     "created_at":"2017-06-26T21:36:23Z",
541 |     "updated_at":"2017-06-26T21:36:23Z",
542 |     "hourly_rate":100.0,
543 |     "budget":null
544 |   },
545 |   "hours":1.0,
546 |   "hours_without_timer":1.0,
547 |   "rounded_hours":1.0,
548 |   "notes":null,
549 |   "created_at":"2017-06-27T16:01:23Z",
550 |   "updated_at":"2017-06-27T16:01:23Z",
551 |   "is_locked":false,
552 |   "locked_reason":null,
553 |   "is_closed":false,
554 |   "is_billed":false,
555 |   "timer_started_at":null,
556 |   "started_time": "8:00am",
557 |   "ended_time": "9:00am",
558 |   "is_running":false,
559 |   "invoice":null,
560 |   "external_reference": null,
561 |   "billable":true,
562 |   "budgeted":true,
563 |   "billable_rate":100.0,
564 |   "cost_rate":50.0
565 | }
566 | Update a time entry⚭
567 | 
568 | Updates the specific time entry by setting the values of the parameters passed. Any parameters not provided will be left unchanged. Returns a time entry object and a 200 OK response code if the call succeeded.
569 | 
570 | PATCH /v2/time_entries/{TIME_ENTRY_ID}
571 | Parameter Type  Description
572 | project_id  integer The ID of the project to associate with the time entry.
573 | task_id integer The ID of the task to associate with the time entry.
574 | spent_date  date  The ISO 8601 formatted date the time entry was spent.
575 | started_time  time  The time the entry started. Defaults to the current time. Example: “8:00am”.
576 | ended_time  time  The time the entry ended.
577 | hours decimal The current amount of time tracked.
578 | notes string  Any notes to be associated with the time entry.
579 | external_reference  object  An object containing the id, group_id, account_id, and permalink of the external reference.
580 | Example Request:
581 | 
582 | curl "<https://api.harvestapp.com/v2/time_entries/636718192>" \
583 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
584 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
585 |   -H "User-Agent: MyApp (<[email protected]>)" \
586 |   -X PATCH \
587 |   -H "Content-Type: application/json" \
588 |   -d '{"notes":"Updated notes"}'
589 | Example Response:
590 | 
591 | {
592 |   "id":636718192,
593 |   "spent_date":"2017-03-21",
594 |   "user":{
595 |     "id":1782959,
596 |     "name":"Kim Allen"
597 |   },
598 |   "client":{
599 |     "id":5735774,
600 |     "name":"ABC Corp"
601 |   },
602 |   "project":{
603 |     "id":14307913,
604 |     "name":"Marketing Website"
605 |   },
606 |   "task":{
607 |     "id":8083365,
608 |     "name":"Graphic Design"
609 |   },
610 |   "user_assignment":{
611 |     "id":125068553,
612 |     "is_project_manager":true,
613 |     "is_active":true,
614 |     "budget":null,
615 |     "created_at":"2017-06-26T22:32:52Z",
616 |     "updated_at":"2017-06-26T22:32:52Z",
617 |     "hourly_rate":100.0
618 |   },
619 |   "task_assignment":{
620 |     "id":155502709,
621 |     "billable":true,
622 |     "is_active":true,
623 |     "created_at":"2017-06-26T21:36:23Z",
624 |     "updated_at":"2017-06-26T21:36:23Z",
625 |     "hourly_rate":100.0,
626 |     "budget":null
627 |   },
628 |   "hours":1.0,
629 |   "hours_without_timer":1.0,
630 |   "rounded_hours":1.0,
631 |   "notes":"Updated notes",
632 |   "created_at":"2017-06-27T16:01:23Z",
633 |   "updated_at":"2017-06-27T16:02:40Z",
634 |   "is_locked":false,
635 |   "locked_reason":null,
636 |   "is_closed":false,
637 |   "is_billed":false,
638 |   "timer_started_at":null,
639 |   "started_time":null,
640 |   "ended_time":null,
641 |   "is_running":false,
642 |   "invoice":null,
643 |   "external_reference": null,
644 |   "billable":true,
645 |   "budgeted":true,
646 |   "billable_rate":100.0,
647 |   "cost_rate":50.0
648 | }
649 | Delete a time entry’s external reference⚭
650 | 
651 | Delete a time entry’s external reference. Returns a 200 OK response code if the call succeeded.
652 | 
653 | DELETE /v2/time_entries/{TIME_ENTRY_ID}/external_reference
654 | Example Request:
655 | 
656 | curl
657 | "<https://api.harvestapp.com/v2/time_entries/636718192/external_reference>" \
658 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
659 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
660 |   -H "User-Agent: MyApp (<[email protected]>)" \
661 |   -X DELETE
662 | Delete a time entry⚭
663 | 
664 | Delete a time entry. Deleting a time entry is only possible if it’s not closed and the associated project and task haven’t been archived. However, Admins can delete closed entries. Returns a 200 OK response code if the call succeeded.
665 | 
666 | DELETE /v2/time_entries/{TIME_ENTRY_ID}
667 | Example Request:
668 | 
669 | curl "<https://api.harvestapp.com/v2/time_entries/636718192>" \
670 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
671 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
672 |   -H "User-Agent: MyApp (<[email protected]>)" \
673 |   -X DELETE
674 | Restart a stopped time entry⚭
675 | 
676 | Restarting a time entry is only possible if it isn’t currently running. Returns a 200 OK response code if the call succeeded.
677 | 
678 | PATCH /v2/time_entries/{TIME_ENTRY_ID}/restart
679 | Example Request:
680 | 
681 | curl "<https://api.harvestapp.com/v2/time_entries/662202797/restart>" \
682 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
683 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
684 |   -H "User-Agent: MyApp (<[email protected]>)" \
685 |   -X PATCH
686 | Example Response:
687 | 
688 | {
689 |   "id": 662204379,
690 |   "spent_date": "2017-03-21",
691 |   "user": {
692 |       "id": 1795925,
693 |       "name": "Jane Smith"
694 |   },
695 |   "client": {
696 |       "id": 5735776,
697 |       "name": "123 Industries"
698 |   },
699 |   "project": {
700 |       "id": 14808188,
701 |       "name": "Task Force"
702 |   },
703 |   "task": {
704 |       "id": 8083366,
705 |       "name": "Programming"
706 |   },
707 |   "user_assignment": {
708 |       "id": 130403296,
709 |       "is_project_manager": true,
710 |       "is_active": true,
711 |       "budget": null,
712 |       "created_at": "2017-08-22T17:36:54Z",
713 |       "updated_at": "2017-08-22T17:36:54Z",
714 |       "hourly_rate": 100
715 |   },
716 |   "task_assignment": {
717 |       "id": 160726645,
718 |       "billable": true,
719 |       "is_active": true,
720 |       "created_at": "2017-08-22T17:36:54Z",
721 |       "updated_at": "2017-08-22T17:36:54Z",
722 |       "hourly_rate": 100,
723 |       "budget": null
724 |   },
725 |   "hours": 0,
726 |   "hours_without_timer": 0,
727 |   "rounded_hours":0,
728 |   "notes": null,
729 |   "created_at": "2017-08-22T17:40:24Z",
730 |   "updated_at": "2017-08-22T17:40:24Z",
731 |   "is_locked": false,
732 |   "locked_reason": null,
733 |   "is_closed": false,
734 |   "is_billed": false,
735 |   "timer_started_at": "2017-08-22T17:40:24Z",
736 |   "started_time": "11:40am",
737 |   "ended_time": null,
738 |   "is_running": true,
739 |   "invoice": null,
740 |   "external_reference": null,
741 |   "billable": true,
742 |   "budgeted": false,
743 |   "billable_rate": 100,
744 |   "cost_rate": 75
745 | }
746 | Stop a running time entry⚭
747 | 
748 | Stopping a time entry is only possible if it’s currently running. Returns a 200 OK response code if the call succeeded.
749 | 
750 | PATCH /v2/time_entries/{TIME_ENTRY_ID}/stop
751 | Example Request:
752 | 
753 | curl "<https://api.harvestapp.com/v2/time_entries/662202797/stop>" \
754 |   -H "Authorization: Bearer $ACCESS_TOKEN" \
755 |   -H "Harvest-Account-Id: $ACCOUNT_ID" \
756 |   -H "User-Agent: MyApp (<[email protected]>)" \
757 |   -X PATCH
758 | Example Response:
759 | 
760 | {
761 |   "id": 662202797,
762 |   "spent_date": "2017-03-21",
763 |   "user": {
764 |       "id": 1795925,
765 |       "name": "Jane Smith"
766 |   },
767 |   "client": {
768 |       "id": 5735776,
769 |       "name": "123 Industries"
770 |   },
771 |   "project": {
772 |       "id": 14808188,
773 |       "name": "Task Force"
774 |   },
775 |   "task": {
776 |       "id": 8083366,
777 |       "name": "Programming"
778 |   },
779 |   "user_assignment": {
780 |       "id": 130403296,
781 |       "is_project_manager": true,
782 |       "is_active": true,
783 |       "budget": null,
784 |       "created_at": "2017-08-22T17:36:54Z",
785 |       "updated_at": "2017-08-22T17:36:54Z",
786 |       "hourly_rate": 100
787 |   },
788 |   "task_assignment": {
789 |       "id": 160726645,
790 |       "billable": true,
791 |       "is_active": true,
792 |       "created_at": "2017-08-22T17:36:54Z",
793 |       "updated_at": "2017-08-22T17:36:54Z",
794 |       "hourly_rate": 100,
795 |       "budget": null
796 |   },
797 |   "hours": 0.02,
798 |   "hours_without_timer": 0.02,
799 |   "rounded_hours":0.25,
800 |   "notes": null,
801 |   "created_at": "2017-08-22T17:37:13Z",
802 |   "updated_at": "2017-08-22T17:38:31Z",
803 |   "is_locked": false,
804 |   "locked_reason": null,
805 |   "is_closed": false,
806 |   "is_billed": false,
807 |   "timer_started_at": null,
808 |   "started_time": "11:37am",
809 |   "ended_time": "11:38am",
810 |   "is_running": false,
811 |   "invoice": null,
812 |   "external_reference": null,
813 |   "billable": true,
814 |   "budgeted": false,
815 |   "billable_rate": 100,
816 |   "cost_rate": 75
817 | }
818 | 
```
Page 2/2FirstPrevNextLast