Conversation
Timesheet operations incorrectly used /buckets/ paths instead of /projects/:
- GetProjectTimesheet, GetRecordingTimesheet, GetTimesheetEntry,
UpdateTimesheetEntry now use /{accountId}/projects/{projectId}/...
Add boosts_count and boosts_url fields to 12 recording type structures:
Todo, Todolist, Comment, Message, Document, Upload, ScheduleEntry,
CampfireLine, Card, ForwardReply, QuestionAnswer, Event.
Add optional content_type parameter to CreateCampfireLine for rich text.
New Boosts service modeling the Basecamp Boosts API:
- ListRecordingBoosts (GET /recordings/{id}/boosts.json)
- ListEventBoosts (GET /recordings/{id}/events/{id}/boosts.json)
- GetBoost (GET /boosts/{id})
- CreateRecordingBoost (POST /recordings/{id}/boosts.json)
- CreateEventBoost (POST /recordings/{id}/events/{id}/boosts.json)
- DeleteBoost (DELETE /boosts/{id})
Includes generated services for all three SDKs (Go, TypeScript, Ruby),
client wiring, and test coverage for all 6 operations.
bc3-api: f7413a2717ced5e38f1ca215cbd95e9d74b02db3 bc3: 37be1c9481c88845c02ac8e4b95319b8d29ad460
There was a problem hiding this comment.
Pull request overview
Synchronizes the SDK with upstream Basecamp API changes (2026-02-07), including corrected timesheet routing under /projects/ and introducing the new Boosts API across the generated clients/tests.
Changes:
- Updated Timesheets endpoints from
/buckets/{projectId}/...to/projects/{projectId}/...and adjusted corresponding TS/Ruby tests. - Added Boosts API operations (list/get/create/delete) plus generated service wiring and new test suites (TS + Ruby).
- Added new fields (
boosts_count,boosts_url,content_type) into the Smithy spec and regenerated SDK artifacts/metadata.
Reviewed changes
Copilot reviewed 16 out of 31 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| typescript/tests/services/reports.test.ts | Updates mocked timesheet URLs to /projects/... in TS tests. |
| typescript/tests/services/boosts.test.ts | Adds new TS test suite for BoostsService. |
| typescript/src/index.ts | Exports the new Boosts service/types from the TS package entrypoint. |
| typescript/src/generated/services/timesheets.ts | Updates generated TimesheetsService paths to /projects/.... |
| typescript/src/generated/services/index.ts | Adds BoostsService to generated service exports. |
| typescript/src/generated/services/campfires.ts | Adds contentType request field and maps it to content_type. |
| typescript/src/generated/services/boosts.ts | New generated Boosts service implementation. |
| typescript/src/generated/schema.d.ts | Updates generated schema typings for boosts + timesheet path changes. |
| typescript/src/generated/path-mapping.ts | Maps new Boosts endpoints and moves timesheet operations to /projects/.... |
| typescript/src/generated/openapi-stripped.json | Updates stripped OpenAPI source for boosts + timesheet path changes. |
| typescript/src/generated/metadata.json | Regenerated TS operation metadata including retry/pagination for boosts and updated timesheet ops. |
| typescript/src/client.ts | Wires BoostsService into the TS client. |
| typescript/scripts/generate-services.ts | Adds Boosts tag-to-service mapping for TS generation. |
| spec/overlays/tags.smithy | Tags Boosts operations for generation. |
| spec/basecamp.smithy | Adds Boosts API shapes/ops, timesheet path fixes, and boosts fields/content_type additions. |
| spec/api-provenance.json | Updates upstream revision stamps to 2026-02-07. |
| ruby/test/basecamp/services/timesheet_service_test.rb | Updates Ruby timesheet tests to expect /projects/... paths. |
| ruby/test/basecamp/services/campfires_service_test.rb | Adds Ruby test for content_type on campfire line creation. |
| ruby/test/basecamp/services/boosts_service_test.rb | Adds Ruby test suite for BoostsService. |
| ruby/scripts/generate-services.rb | Adds Boosts tag-to-service mapping for Ruby generation. |
| ruby/lib/basecamp/generated/types.rb | Regenerates Ruby types to include Boost + boosts_count/url fields. |
| ruby/lib/basecamp/generated/services/timesheets_service.rb | Updates generated Ruby timesheet paths to /projects/.... |
| ruby/lib/basecamp/generated/services/campfires_service.rb | Adds content_type support to Ruby campfire line creation. |
| ruby/lib/basecamp/generated/services/boosts_service.rb | Adds generated BoostsService in Ruby. |
| ruby/lib/basecamp/generated/metadata.json | Regenerates Ruby operation metadata (boosts + moved timesheet ops). |
| ruby/lib/basecamp/client.rb | Exposes boosts accessor on the Ruby client. |
| go/pkg/basecamp/url-routes.json | Adds route entries for Boosts + new /projects/... timesheet routes. |
| go/pkg/basecamp/api-provenance.json | Updates Go provenance stamps to 2026-02-07. |
| behavior-model.json | Adds behavior/retry/pagination metadata for Boosts operations. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Add METHOD_NAME_OVERRIDES for compound boost operations and "boost" to isSimpleResource so generated interface names read cleanly: - ListForRecordingBoostOptions (was ListRecordingBoostsBoostOptions) - CreateForRecordingBoostRequest (was CreateRecordingBoostBoostRequest) - ListForEventBoostOptions (was ListEventBoostsBoostOptions) - CreateForEventBoostRequest (was CreateEventBoostBoostRequest) Method names also simplified: get/delete for single-boost ops, listForRecording/createForRecording/listForEvent/createForEvent for scoped operations.
jeremy
added a commit
that referenced
this pull request
Feb 8, 2026
Wraps the generated Boosts API client methods added in PR #83: - ListRecording, ListEvent, Get, CreateRecording, CreateEvent, Delete - Converter boostFromGenerated maps generated types to clean SDK types - Lazy-init Boosts() accessor on AccountClient - Fixture-based tests for unmarshal and request serialization
6 tasks
jeremy
added a commit
that referenced
this pull request
Feb 8, 2026
…nt (#84) * Go SDK: Add BoostsService with 6 operations Wraps the generated Boosts API client methods added in PR #83: - ListRecording, ListEvent, Get, CreateRecording, CreateEvent, Delete - Converter boostFromGenerated maps generated types to clean SDK types - Lazy-init Boosts() accessor on AccountClient - Fixture-based tests for unmarshal and request serialization * Go SDK: Expose content_type on CreateLine for campfire messages Add CreateLineOptions parameter to CampfiresService.CreateLine so callers can send HTML content. Validates content_type is text/plain or text/html. Adds LineContentTypePlain and LineContentTypeHTML constants. * Wire drift check into make check and CI - Add test coverage detection to check-service-drift.sh (warns on wrapped operations with no tests calling the generated client) - Add go-check-drift to the check target so make catches drift - Add drift check step to the Go test job in CI * Address Copilot review feedback - Remove unused CreateBoostRequest type (service methods take raw content string, matching CreateLine pattern; struct was only used in tests) - Remove noisy UNTESTED detection from drift check script — tests exercise service wrappers, not .gen.* directly, so the grep produced all-false- positive output for every wrapped operation * Address Codex review: variadic CreateLine opts, service-level validation tests - Change CreateLine signature from *CreateLineOptions to ...CreateLineOptions to preserve source compatibility with existing 4-arg callers - Add service-level validation tests for CampfiresService (empty content, invalid content_type, valid content_types, no-options backward compat) - Add service-level validation tests for BoostsService (empty content rejected, valid content accepted) * Add httptest-based service contract tests for Boosts and CreateLine BoostsService tests (7 new): - ListRecording: 200 response, X-Total-Count header parsing, converter mapping - ListRecording empty: 200 with [] body - Get: 200 with full converter mapping (Booster, Recording) - Get 404: not_found error - CreateRecording: 201, verifies request body content wiring - Delete: 204 success - Delete 404: not_found error CampfiresService CreateLine tests (3 new, replacing panic-based tests): - NoOptions: POST with content only, no content_type in request body - HTMLOption: content_type=text/html flows through to request body - PlainOption: content_type=text/plain flows through to request body Uses testBoostsServer/testCampfiresServer helpers that wire httptest.Server through NewClient → ForAccount → service, exercising the full call path including generated client, checkResponse, and type converters. * Address review: gofmt, remove panic tests, cover all 6 Boost ops, reject extra opts - Fix trailing newline gofmt issue in boosts_test.go - Remove panic-recovery validation tests (superseded by httptest tests) - Add httptest tests for ListEvent and CreateEvent (all 6 BoostsService operations now have service contract tests) - Reject len(opts) > 1 in CreateLine with ErrUsage instead of silently ignoring extra options - Fix unparam lint: test helpers return *Service only, not (*Service, *Server)
jeremy
added a commit
that referenced
this pull request
Feb 8, 2026
Flatten the 6 new Boost operation URIs from PR #83 to remove /buckets/{projectId} nesting, matching the flat branch convention. Regenerate all SDK clients and update tests for flat paths. Add web-URL flattening to Go router so it can match Basecamp web URLs (which still contain /buckets/{projectId}) against the flat route table.
jeremy
added a commit
that referenced
this pull request
Feb 8, 2026
Flatten the 6 new Boost operation URIs from PR #83 to remove /buckets/{projectId} nesting, matching the flat branch convention. Regenerate all SDK clients and update tests for flat paths. Add web-URL flattening to Go router so it can match Basecamp web URLs (which still contain /buckets/{projectId}) against the flat route table.
jeremy
added a commit
that referenced
this pull request
Feb 20, 2026
Flatten the 6 new Boost operation URIs from PR #83 to remove /buckets/{projectId} nesting, matching the flat branch convention. Regenerate all SDK clients and update tests for flat paths. Add web-URL flattening to Go router so it can match Basecamp web URLs (which still contain /buckets/{projectId}) against the flat route table.
jeremy
added a commit
that referenced
this pull request
Feb 20, 2026
Flatten the 6 new Boost operation URIs from PR #83 to remove /buckets/{projectId} nesting, matching the flat branch convention. Regenerate all SDK clients and update tests for flat paths. Add web-URL flattening to Go router so it can match Basecamp web URLs (which still contain /buckets/{projectId}) against the flat route table.
jeremy
added a commit
that referenced
this pull request
Feb 26, 2026
Flatten the 6 new Boost operation URIs from PR #83 to remove /buckets/{projectId} nesting, matching the flat branch convention. Regenerate all SDK clients and update tests for flat paths. Add web-URL flattening to Go router so it can match Basecamp web URLs (which still contain /buckets/{projectId}) against the flat route table.
jeremy
added a commit
that referenced
this pull request
Feb 27, 2026
Flatten the 6 new Boost operation URIs from PR #83 to remove /buckets/{projectId} nesting, matching the flat branch convention. Regenerate all SDK clients and update tests for flat paths. Add web-URL flattening to Go router so it can match Basecamp web URLs (which still contain /buckets/{projectId}) against the flat route table.
jeremy
added a commit
that referenced
this pull request
Feb 27, 2026
* Flatten Smithy spec routes to remove nested URL scoping
Resources are uniquely identified and don't need parentage context in
their URLs. Remove /buckets/{projectId} prefix and other nested scoping
from ~80 operations, changing paths like:
/{accountId}/buckets/{projectId}/todos/{todoId}
to flat paths like:
/{accountId}/todos/{todoId}
Project-scoped operations under /projects/{projectId}/ are retained
since those genuinely operate on the project resource itself.
* Regenerate all SDK clients from flattened OpenAPI spec
* Update Go service layer for flat routes
Remove projectID parameter from all service methods that no longer
need bucket scoping. Retain projectID only for genuinely project-scoped
operations (ListProjectPeople, UpdateProjectAccess).
Also simplifies lineup marker requests to match spec (name/date only),
and removes BucketID from OperationInfo and OpenTelemetry spans.
* Update Go tests for flat route signatures
Remove projectID arguments from test calls, update lineup test
fixtures to use name/date fields, and remove BucketID from
observability test assertions.
* Update TypeScript tests for flat routes
Remove /buckets/{projectId} from MSW mock URLs, remove projectId
arguments from service calls, update lineup tests to use name/date
fields, and remove project_id from OpenTelemetry span assertions.
* Update Ruby tests for flat routes
Remove project_id: keyword arguments from service test calls, update
WebMock stub URLs to use flat paths, update lineup tests to use
name/date fields, and fix card step completion tests to use
set_card_step_completion on CardTablesService.
* Update conformance runner for flat routes
Remove projectId argument from CreateTodo and ListTodos calls in
the conformance test runner.
* Remove unused bucketID parameters from Go service methods
Nine methods still accepted a bucketID parameter that was silently
discarded — callers would pass a value that got thrown away. Remove
the parameter from: CampfiresService.GetLine, DeleteLine, GetChatbot,
UpdateChatbot, DeleteChatbot; ForwardsService.GetReply;
ClientRepliesService.Get; CardsService.Move; CardStepsService.Reposition.
Also remove dead ProjectPath() and RequireProject() methods from Client.
* Remove stale bucketID comments from Go service files
Clean 121 comment lines across 22 files that referenced bucketID
parameters that no longer exist in function signatures.
* Flatten conformance test paths to match new flat routes
Remove /buckets/{projectId} prefix from test path patterns and
projectId from pathParams in pagination, idempotency, and status-code
conformance tests. Update schema.json example accordingly.
* Update README examples and cleanup stale bucket references
Remove projectId arguments from Go, TypeScript, and Ruby README code
examples to match flattened service signatures. Update TS
normalizeUrlPath JSDoc comment. Remove dead bucket_path codegen logic
from Ruby service generator.
* Flatten timesheet entry operations added by PR #76
The rebase onto main brought in 3 new timesheet entry operations
(Get, Create, Update) with nested /buckets/{projectId}/ URIs.
Flatten these to match the rest of the flat branch, regenerate
all SDK clients, and update the Go service layer and conformance
runner accordingly.
* Remove dead hand-written TypeScript service files
These 31 files were superseded by generated services in
src/generated/services/ but never deleted. The entry point
(src/index.ts) already imports from generated, so these were
unused dead code. Only base.ts and authorization.ts remain
as hand-written services (they talk to different endpoints).
The ts-service branch will address generating a single unified
service layer that matches the ergonomics of these originals.
* Fix Ruby card_steps test and remove stale .plan.md
Update card_steps_service_test.rb to use the regenerated method
name (card_steps.set_completion instead of card_tables.set_card_step_completion).
Remove .plan.md that was accidentally included during rebase.
* Regenerate all SDK clients from canonical openapi.json
Post-rebase regeneration to ensure generated files match the
canonical openapi.json built from the Smithy spec.
* Flatten Boost API operations and regenerate all SDK clients
Flatten the 6 new Boost operation URIs from PR #83 to remove
/buckets/{projectId} nesting, matching the flat branch convention.
Regenerate all SDK clients and update tests for flat paths.
Add web-URL flattening to Go router so it can match Basecamp web URLs
(which still contain /buckets/{projectId}) against the flat route table.
* Flatten Go BoostsService and CreateLine for flat branch
Remove bucketID parameter from all 6 BoostsService methods and
update CreateLine test calls to match flat campfire signatures.
* Fix URL router missing .json-suffixed API URLs
The route table strips .json suffixes during generation, but the
router was matching against the raw path. API URLs like
basecampapi.com/.../boosts.json returned nil because the route
table stores .../boosts without the suffix.
Fix by normalizing .json in extractPath alongside other URL
normalization (scheme, host, query, trailing slash).
* Flatten webhook get-with-deliveries test URLs for flat branch
Remove /buckets/{projectId} from TS and Ruby webhook test that
was added in PR #85 for the recent_deliveries fixture test.
* Fix Go SDK build: wrap *int64 Id fields with derefInt64() in all converters
The required-fields PR changed all Id fields in generated types from
int64 to *int64. Update all *FromGenerated converter functions to use
derefInt64() for pointer-to-value conversion, and update test struct
literals to pass pointer values.
* Regenerate all SDK clients from Smithy spec and fix CI
Rebuild openapi.json from Smithy, then regenerate Ruby, TypeScript,
and Kotlin SDKs. Updates Kotlin conformance tests and TodosServiceTest
for flat URL signatures (projectId removed). Fixes apidiff CI cache
key to include go.mod hash so the tool rebuilds on Go version bumps.
* Fix spec routes C1, C2, C5, C6 and regenerate all SDKs
C1: GetProjectTimeline now bucket-scoped at /buckets/{projectId}/timeline.json
C2: GetProjectTimesheet now bucket-scoped at /buckets/{projectId}/timesheet.json
C5: Timesheet entry routes use /timesheet_entries/{entryId} (underscore separator)
C6: ListWebhooks/CreateWebhook now bucket-scoped at /buckets/{bucketId}/webhooks.json
Propagated across Go (generated + hand-written), Ruby, TypeScript, Kotlin, Swift.
Go URL router handles /projects/ → /buckets/ normalization for web URLs.
TS normalizeUrlPath uses context overrides for bucketId vs projectId.
Conformance tests cover all four route fixes (Go 31/31, Kotlin 30/30+1 skip).
* Fix PR review comments: update stale docs and comments
- Go README: Add bucketID to webhook Create/List examples
- Go README: Define boardID variable in message board example
- timesheet.go: Remove stale projectID reference from RecordingReport comment
- message_types.go: Update List comment to reflect account-level scope
* Fix timeline/timesheet paths: /buckets/ → /projects/
BC3 serves GetProjectTimeline and GetProjectTimesheet at
/projects/{projectId}/... not /buckets/{projectId}/...
Main branch already had this fix but flat never picked it up.
* Update conformance and SDK tests for /projects/ timeline/timesheet paths
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Brings the SDK current with upstream Basecamp API changes (2026-02-07):
/buckets/to/projects/(GetProjectTimesheet,GetRecordingTimesheet,GetTimesheetEntry,UpdateTimesheetEntry)boosts_countandboosts_urlon 12 recording types;content_typeonCreateCampfireLineInputfor rich text campfire linesListRecordingBoosts,ListEventBoosts,GetBoost,CreateRecordingBoost,CreateEventBoost,DeleteBoost— with full service wiring in all three SDKsCommits
bc3_apiandbc3revisionsTest plan
make checkpasses (all three SDKs compile and test green)/projects/paths