Skip to content

Timesheet API: document create, update, and trash endpoints#376

Merged
jeremy merged 1 commit intomasterfrom
timesheet-api
Feb 5, 2026
Merged

Timesheet API: document create, update, and trash endpoints#376
jeremy merged 1 commit intomasterfrom
timesheet-api

Conversation

@jeremy
Copy link
Member

@jeremy jeremy commented Feb 5, 2026

Summary

  • Document the new POST endpoint for creating timesheet entries (date, hours, description, person_id)
  • Document the PUT endpoint for updating entries
  • Link to the shared recordings trash endpoint
  • Include auto-generated JSON response examples for create and update

Companion to basecamp/bc3#9590.

Test plan

  • JSON response examples generated via ./script/api/update_docs
  • README endpoint list updated automatically

Copilot AI review requested due to automatic review settings February 5, 2026 05:49
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: db3cf6251d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds comprehensive API documentation for creating and updating timesheet entries in the Basecamp 4 API. It includes detailed endpoint specifications, parameter descriptions, JSON request/response examples, and cURL commands following the established documentation patterns.

Changes:

  • Added documentation for POST endpoint to create timesheet entries with date, hours, description, and person_id parameters
  • Added documentation for PUT endpoint to update existing timesheet entries
  • Added link to the shared recordings trash endpoint for deleting timesheet entries
  • Removed Authentication from auto-generated API endpoints list in README (intentional cleanup)

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
sections/timesheets.md Added complete documentation for creating and updating timesheet entries, including required/optional parameters, JSON examples, and cURL commands
README.md Removed Authentication line from auto-generated API endpoints list (appears to be intentional cleanup)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Add documentation for the new write endpoints:
- POST to create timesheet entries with date, hours, description
- PUT to update existing entries
- Trash via the shared recordings endpoint

Includes auto-generated JSON response examples.
@jeremy jeremy merged commit c27095b into master Feb 5, 2026
@jeremy jeremy deleted the timesheet-api branch February 5, 2026 06:16
jeremy added a commit that referenced this pull request Feb 5, 2026
Add the "Get a timesheet entry" show endpoint and include the person
(who the time is logged for) in all timesheet entry JSON responses.

Follows up on #376 which documented the write endpoints.
jeremy added a commit that referenced this pull request Feb 5, 2026
Add the "Get a timesheet entry" show endpoint and include the person
(who the time is logged for) in all timesheet entry JSON responses.

Follows up on #376 which documented the write endpoints.
@alexbudin
Copy link

@jeremy

Not sure if there is an issue with the Timesheet API or i am doing something wrong. Ive run a lot of tests on it and i think there is also a documentation error in regards to the CREATE endpoint.

Please confirm you are seeing this message as i am not sure you get this after this has been closed.

Basecamp Timesheet API Curl Tests

Base URL: https://3.basecampapi.com/XXXXXXX

XXXXXXX - is my account ID
Authorization header: Bearer <access_token> (from OAuth login).
The user used is an Admin and Owner and has access to the project (is creator of project)


GET Requests (All Successful)

# URL Path HTTP Result
1 GET /projects/43420314.json 200 Full project JSON. timesheet_enabled: true, dock listing with todoset, message_board, vault, etc.
2 GET /buckets/43420314/todosets/8939176616/todolists.json 200 Todolists: id=8939313304
3 GET /buckets/43420314/todolists/8939313304/todos.json 200 Todos: id=8939314382
4 GET /projects/43420314/timesheet.json 200 Existing timesheet entries.

Conclusion: All GET endpoints work.


POST Requests — /buckets/ Path (All 404 — HTML Error Page)

All returned HTML 404: "Sorry, we don't have anything to show you here"

# URL Path Body HTTP
5 POST /buckets/43420314/recordings/8939176616/timesheet/entries.json {"date":"2026-02-15","hours":"0.25","description":"API test"} 404
6 POST /buckets/43420314/recordings/8939314382/timesheet/entries.json {"date":"2026-02-15","hours":"0.25","description":"curl test from todo"} 404
7 POST /buckets/43420314/recordings/8939176614/timesheet/entries.json {"date":"2026-02-15","hours":"0.25","description":"curl test with timesheet recording"} 404
8 POST /buckets/43420314/recordings/8939394639/timesheet/entries.json {"date":"2026-02-14","hours":"1:30","description":"Client meeting prep"} 404

Conclusion: /buckets/ path does not work for POST on this account. Returns HTML, not JSON.


POST Requests — /projects/ Path with Recording (All 400)

All returned {"status":400,"error":"Bad Request"} with no additional detail.

# URL Path Body HTTP
9 POST /projects/43420314/recordings/8939176616/timesheet/entries.json {"date":"2026-02-15","hours":"0.25","description":"API test"} 404 (recording 8939176616 is a todoset, not valid)
10 POST /projects/43420314/recordings/8939176614/timesheet/entries.json {"date":"2026-02-15","hours":"0.25","description":"curl test projects path"} 400
11 POST /projects/43420314/recordings/8939176614/timesheet/entries.json {"date":"2026-02-15","hours":"1.0","description":"curl test"} 400
12 POST /projects/43420314/recordings/8939176614/timesheet/entries.json {"date":"2026-02-16","hours":"2"} 400
13 POST /projects/43420314/recordings/8939314382/timesheet/entries.json {"date":"2026-02-16","hours":"2"} 400
14 POST /projects/43420314/recordings/8939314382/timesheet/entries.json {"date":"2026-02-16","hours":"2","description":"test entry via API"} 400
15 POST /projects/43420314/recordings/8939314382/timesheet/entries.json {"date":"2026-02-16","hours":"1:30","description":"API test time format"} 400
16 POST /projects/43420314/recordings/8939394639/timesheet/entries.json {"date":"2026-02-14","hours":"2.0","description":"curl test entry"} 400
17 POST /projects/43420314/recordings/8939394639/timesheet/entries.json {"date":"2026-02-14","hours":"2.0","description":"test"} (different User-Agent) 400
18 POST /projects/43420314/recordings/8939394639/timesheet/entries.json {} (empty body) 400

Variations tested (all 400):

  • Hours formats: "0.25", "1.0", "2", "2.0", "1:30"
  • With/without description
  • Empty body {}
  • Different User-Agent strings
  • With/without Accept header

POST Requests — /projects/.../timesheet/entries.json (No Recording — All 404)

Attempted project-level timesheet entry (no recording segment). All returned HTML 404.

# URL Path Body HTTP
19 POST /projects/43420314/timesheet/entries.json {"date":"2026-02-15","hours":"0.25","description":"API test"} 404
20 POST /projects/43420314/timesheet/entries.json {"date":"2026-02-16","hours":"0.5","description":"test project level entry"} 404
21 POST /projects/43420314/timesheet/entries.json {"recording_id":8939394639,"date":"2026-02-14","hours":"2.0","description":"test with recording in body"} 404

PUT Requests (Update Existing Entry — Both Failed)

Attempted to update existing entry 9501969593.

# URL Path Body HTTP Response
22 PUT /buckets/43420314/timesheet/entries/9501969593.json {"description":"updated via API test"} 404 HTML error page
23 PUT /projects/43420314/timesheet/entries/9501969593.json {"description":"updated via API test"} 400 {"status":400,"error":"Bad Request"}

Summary

  • All reads work — OAuth token has valid read access
  • All writes fail — every POST and PUT returns 400 or 404
  • /buckets/ path: always HTML 404 (route doesn't exist on this account) - used for POST in the documentation for Timesheets
  • /projects/ path: always JSON 400 {"status":400,"error":"Bad Request"} (no details) - which is not the one used for POST in the documentation for Timesheets
  • Tried every combination of recording IDs, hour formats, body content, headers

i have a feeling that there is some writing permission problem.

@jeremy
Copy link
Member Author

jeremy commented Feb 16, 2026

Confirmed @alexbudin! Updated docs with wrong paths; fixing. Thanks for reporting.

jeremy added a commit that referenced this pull request Feb 16, 2026
The create and update endpoint descriptions and cURL examples
incorrectly used `/buckets/` in the URL path, but the routes
only exist under `/projects/`. This caused 404s for customers
following the documentation.

Fixes #376 (comment)
@alexbudin
Copy link

@jeremy BUT why do i get 400 even if i use the /projects entry endpoint?

@jeremy
Copy link
Member Author

jeremy commented Feb 16, 2026

@alexbudin JSON params wrapping bug. Fixing that too!

@alexbudin
Copy link

i keep testing every 30 minutes :))))

jeremy added a commit that referenced this pull request Feb 16, 2026
The create and update endpoint descriptions and cURL examples
incorrectly used `/buckets/` in the URL path, but the routes
only exist under `/projects/`. This caused 404s for customers
following the documentation.

Fixes #376 (comment)
@jeremy
Copy link
Member Author

jeremy commented Feb 16, 2026

@alexbudin Fix deployed.

@alexbudin
Copy link

Works! Thank you so munch!

@alexbudin
Copy link

@jeremy Was reading the documentation more closely and noticed that there is no mention on how to add time to the project only, without specifying a todo. is it possible to add hours directly to the project like in the platform? or a todo must be specified in the endpoint url?

@jeremy
Copy link
Member Author

jeremy commented Feb 18, 2026

@alexbudin it is possible, but not discoverable: get the project timesheet from the dock first, then POST /projects/:id/recordings/:recording_id/timesheet/entries.json. I'll document and make it discoverable.

@jeremy
Copy link
Member Author

jeremy commented Feb 18, 2026

@alexbudin documented here: #382

@alexbudin
Copy link

Awesome!. ill have a play a bit later today with this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants