basecamp-sdk 0.27.0 → 0.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69a94db94f0ff533b6160519f9ed6e41089ef70639d36e7042668f8ba5c819e9
4
- data.tar.gz: a19a2cf4cff6180e1671e826bc6a9e93794576c05af574c0cd0ab64296a361e7
3
+ metadata.gz: 4bc60f80b34fcacfc0d5bbebebd7b56b19043ce5c34522e86b72a7e802d5a89f
4
+ data.tar.gz: 30bf19a62baffdb5562e86149a5f016bfe443f54ad2a0968bb971cc31531fce4
5
5
  SHA512:
6
- metadata.gz: bec94397b02003677dd55ce96cb2786c4d0f8b502097f564086187c74ba767e6191b0104ca9d67eaece577664646a1f6828e877b9407e2f6c7613ad9c8c36c5d
7
- data.tar.gz: 5523532f3233eecefc27ec7ca6c0048513f66fee6b53986be5458c120f83f75be65509de87eaeb22e84f2814356f30758d64fb1df392cc63dc5a76bb2bb7d8b5
6
+ metadata.gz: 33d7bb7a1846b77016d350ed858e2981f1b37bddada71f1e033e3ef50f7c7a4e333f52567d62822d4587f2db66f8f84648f038d7a5bcd8bd54c7f675bd540416
7
+ data.tar.gz: c0da32ba141bbd064a2edee6ee231874be9de43080a02b95f78a6465bd90f287438a98379e50007a003cc06b82d2108c1ad71743e11366191146f987c67a52bd
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://basecamp.com/schemas/sdk-metadata.json",
3
3
  "version": "1.0.0",
4
- "generated": "2026-10-20T15:47:49Z",
4
+ "generated": "2026-10-23T22:09:28Z",
5
5
  "operations": {
6
6
  "GetAccount": {
7
7
  "retry": {
@@ -2069,6 +2069,34 @@
2069
2069
  "maxPageSize": 50
2070
2070
  }
2071
2071
  },
2072
+ "UpdateProjectWallpaper": {
2073
+ "retry": {
2074
+ "maxAttempts": 3,
2075
+ "baseDelayMs": 1000,
2076
+ "backoff": "exponential",
2077
+ "retryOn": [
2078
+ 429,
2079
+ 503
2080
+ ]
2081
+ },
2082
+ "idempotent": {
2083
+ "natural": true
2084
+ }
2085
+ },
2086
+ "RemoveProjectWallpaper": {
2087
+ "retry": {
2088
+ "maxAttempts": 3,
2089
+ "baseDelayMs": 1000,
2090
+ "backoff": "exponential",
2091
+ "retryOn": [
2092
+ 429,
2093
+ 503
2094
+ ]
2095
+ },
2096
+ "idempotent": {
2097
+ "natural": true
2098
+ }
2099
+ },
2072
2100
  "GetAnswer": {
2073
2101
  "retry": {
2074
2102
  "maxAttempts": 3,
@@ -3765,10 +3793,12 @@
3765
3793
  "CreateCard": [
3766
3794
  "assignees.[]",
3767
3795
  "completer",
3796
+ "completion.creator",
3768
3797
  "completion_subscribers.[]",
3769
3798
  "creator",
3770
3799
  "steps.[].assignees.[]",
3771
3800
  "steps.[].completer",
3801
+ "steps.[].completion.creator",
3772
3802
  "steps.[].creator"
3773
3803
  ],
3774
3804
  "CreateCardColumn": [
@@ -3778,6 +3808,7 @@
3778
3808
  "CreateCardStep": [
3779
3809
  "assignees.[]",
3780
3810
  "completer",
3811
+ "completion.creator",
3781
3812
  "creator"
3782
3813
  ],
3783
3814
  "CreateCloudFile": [
@@ -3817,6 +3848,7 @@
3817
3848
  "CreateSubtask": [
3818
3849
  "assignees.[]",
3819
3850
  "completer",
3851
+ "completion.creator",
3820
3852
  "creator"
3821
3853
  ],
3822
3854
  "CreateTemplateLibraryCardTable": [
@@ -3851,10 +3883,12 @@
3851
3883
  ],
3852
3884
  "CreateTodo": [
3853
3885
  "assignees.[]",
3886
+ "completion.creator",
3854
3887
  "completion_subscribers.[]",
3855
3888
  "creator",
3856
3889
  "steps.[].assignees.[]",
3857
3890
  "steps.[].completer",
3891
+ "steps.[].completion.creator",
3858
3892
  "steps.[].creator"
3859
3893
  ],
3860
3894
  "CreateTodolist": [
@@ -3865,10 +3899,12 @@
3865
3899
  ],
3866
3900
  "CreateTodosetTodo": [
3867
3901
  "assignees.[]",
3902
+ "completion.creator",
3868
3903
  "completion_subscribers.[]",
3869
3904
  "creator",
3870
3905
  "steps.[].assignees.[]",
3871
3906
  "steps.[].completer",
3907
+ "steps.[].completion.creator",
3872
3908
  "steps.[].creator"
3873
3909
  ],
3874
3910
  "CreateTool": [
@@ -3908,10 +3944,12 @@
3908
3944
  "GetAssignedTodos": [
3909
3945
  "person",
3910
3946
  "todos.[].assignees.[]",
3947
+ "todos.[].completion.creator",
3911
3948
  "todos.[].completion_subscribers.[]",
3912
3949
  "todos.[].creator",
3913
3950
  "todos.[].steps.[].assignees.[]",
3914
3951
  "todos.[].steps.[].completer",
3952
+ "todos.[].steps.[].completion.creator",
3915
3953
  "todos.[].steps.[].creator"
3916
3954
  ],
3917
3955
  "GetBoost": [
@@ -3930,10 +3968,12 @@
3930
3968
  "GetCard": [
3931
3969
  "assignees.[]",
3932
3970
  "completer",
3971
+ "completion.creator",
3933
3972
  "completion_subscribers.[]",
3934
3973
  "creator",
3935
3974
  "steps.[].assignees.[]",
3936
3975
  "steps.[].completer",
3976
+ "steps.[].completion.creator",
3937
3977
  "steps.[].creator"
3938
3978
  ],
3939
3979
  "GetCardColumn": [
@@ -3943,6 +3983,7 @@
3943
3983
  "GetCardStep": [
3944
3984
  "assignees.[]",
3945
3985
  "completer",
3986
+ "completion.creator",
3946
3987
  "creator"
3947
3988
  ],
3948
3989
  "GetCardTable": [
@@ -3981,18 +4022,22 @@
3981
4022
  "GetEverythingCompletedCards": [
3982
4023
  "[].cards.[].assignees.[]",
3983
4024
  "[].cards.[].completer",
4025
+ "[].cards.[].completion.creator",
3984
4026
  "[].cards.[].completion_subscribers.[]",
3985
4027
  "[].cards.[].creator",
3986
4028
  "[].cards.[].steps.[].assignees.[]",
3987
4029
  "[].cards.[].steps.[].completer",
4030
+ "[].cards.[].steps.[].completion.creator",
3988
4031
  "[].cards.[].steps.[].creator"
3989
4032
  ],
3990
4033
  "GetEverythingCompletedTodos": [
3991
4034
  "[].todos.[].assignees.[]",
4035
+ "[].todos.[].completion.creator",
3992
4036
  "[].todos.[].completion_subscribers.[]",
3993
4037
  "[].todos.[].creator",
3994
4038
  "[].todos.[].steps.[].assignees.[]",
3995
4039
  "[].todos.[].steps.[].completer",
4040
+ "[].todos.[].steps.[].completion.creator",
3996
4041
  "[].todos.[].steps.[].creator"
3997
4042
  ],
3998
4043
  "GetEverythingFiles": [
@@ -4007,78 +4052,96 @@
4007
4052
  "GetEverythingNoDueDateCards": [
4008
4053
  "[].cards.[].assignees.[]",
4009
4054
  "[].cards.[].completer",
4055
+ "[].cards.[].completion.creator",
4010
4056
  "[].cards.[].completion_subscribers.[]",
4011
4057
  "[].cards.[].creator",
4012
4058
  "[].cards.[].steps.[].assignees.[]",
4013
4059
  "[].cards.[].steps.[].completer",
4060
+ "[].cards.[].steps.[].completion.creator",
4014
4061
  "[].cards.[].steps.[].creator"
4015
4062
  ],
4016
4063
  "GetEverythingNoDueDateTodos": [
4017
4064
  "[].todos.[].assignees.[]",
4065
+ "[].todos.[].completion.creator",
4018
4066
  "[].todos.[].completion_subscribers.[]",
4019
4067
  "[].todos.[].creator",
4020
4068
  "[].todos.[].steps.[].assignees.[]",
4021
4069
  "[].todos.[].steps.[].completer",
4070
+ "[].todos.[].steps.[].completion.creator",
4022
4071
  "[].todos.[].steps.[].creator"
4023
4072
  ],
4024
4073
  "GetEverythingNotNowCards": [
4025
4074
  "[].cards.[].assignees.[]",
4026
4075
  "[].cards.[].completer",
4076
+ "[].cards.[].completion.creator",
4027
4077
  "[].cards.[].completion_subscribers.[]",
4028
4078
  "[].cards.[].creator",
4029
4079
  "[].cards.[].steps.[].assignees.[]",
4030
4080
  "[].cards.[].steps.[].completer",
4081
+ "[].cards.[].steps.[].completion.creator",
4031
4082
  "[].cards.[].steps.[].creator"
4032
4083
  ],
4033
4084
  "GetEverythingOpenCards": [
4034
4085
  "[].cards.[].assignees.[]",
4035
4086
  "[].cards.[].completer",
4087
+ "[].cards.[].completion.creator",
4036
4088
  "[].cards.[].completion_subscribers.[]",
4037
4089
  "[].cards.[].creator",
4038
4090
  "[].cards.[].steps.[].assignees.[]",
4039
4091
  "[].cards.[].steps.[].completer",
4092
+ "[].cards.[].steps.[].completion.creator",
4040
4093
  "[].cards.[].steps.[].creator"
4041
4094
  ],
4042
4095
  "GetEverythingOpenTodos": [
4043
4096
  "[].todos.[].assignees.[]",
4097
+ "[].todos.[].completion.creator",
4044
4098
  "[].todos.[].completion_subscribers.[]",
4045
4099
  "[].todos.[].creator",
4046
4100
  "[].todos.[].steps.[].assignees.[]",
4047
4101
  "[].todos.[].steps.[].completer",
4102
+ "[].todos.[].steps.[].completion.creator",
4048
4103
  "[].todos.[].steps.[].creator"
4049
4104
  ],
4050
4105
  "GetEverythingOverdueCards": [
4051
4106
  "[].assignees.[]",
4052
4107
  "[].completer",
4108
+ "[].completion.creator",
4053
4109
  "[].completion_subscribers.[]",
4054
4110
  "[].creator",
4055
4111
  "[].steps.[].assignees.[]",
4056
4112
  "[].steps.[].completer",
4113
+ "[].steps.[].completion.creator",
4057
4114
  "[].steps.[].creator"
4058
4115
  ],
4059
4116
  "GetEverythingOverdueTodos": [
4060
4117
  "[].assignees.[]",
4118
+ "[].completion.creator",
4061
4119
  "[].completion_subscribers.[]",
4062
4120
  "[].creator",
4063
4121
  "[].steps.[].assignees.[]",
4064
4122
  "[].steps.[].completer",
4123
+ "[].steps.[].completion.creator",
4065
4124
  "[].steps.[].creator"
4066
4125
  ],
4067
4126
  "GetEverythingUnassignedCards": [
4068
4127
  "[].cards.[].assignees.[]",
4069
4128
  "[].cards.[].completer",
4129
+ "[].cards.[].completion.creator",
4070
4130
  "[].cards.[].completion_subscribers.[]",
4071
4131
  "[].cards.[].creator",
4072
4132
  "[].cards.[].steps.[].assignees.[]",
4073
4133
  "[].cards.[].steps.[].completer",
4134
+ "[].cards.[].steps.[].completion.creator",
4074
4135
  "[].cards.[].steps.[].creator"
4075
4136
  ],
4076
4137
  "GetEverythingUnassignedTodos": [
4077
4138
  "[].todos.[].assignees.[]",
4139
+ "[].todos.[].completion.creator",
4078
4140
  "[].todos.[].completion_subscribers.[]",
4079
4141
  "[].todos.[].creator",
4080
4142
  "[].todos.[].steps.[].assignees.[]",
4081
4143
  "[].todos.[].steps.[].completer",
4144
+ "[].todos.[].steps.[].completion.creator",
4082
4145
  "[].todos.[].steps.[].creator"
4083
4146
  ],
4084
4147
  "GetForward": [
@@ -4119,28 +4182,36 @@
4119
4182
  ],
4120
4183
  "GetOverdueTodos": [
4121
4184
  "over_a_month_late.[].assignees.[]",
4185
+ "over_a_month_late.[].completion.creator",
4122
4186
  "over_a_month_late.[].completion_subscribers.[]",
4123
4187
  "over_a_month_late.[].creator",
4124
4188
  "over_a_month_late.[].steps.[].assignees.[]",
4125
4189
  "over_a_month_late.[].steps.[].completer",
4190
+ "over_a_month_late.[].steps.[].completion.creator",
4126
4191
  "over_a_month_late.[].steps.[].creator",
4127
4192
  "over_a_week_late.[].assignees.[]",
4193
+ "over_a_week_late.[].completion.creator",
4128
4194
  "over_a_week_late.[].completion_subscribers.[]",
4129
4195
  "over_a_week_late.[].creator",
4130
4196
  "over_a_week_late.[].steps.[].assignees.[]",
4131
4197
  "over_a_week_late.[].steps.[].completer",
4198
+ "over_a_week_late.[].steps.[].completion.creator",
4132
4199
  "over_a_week_late.[].steps.[].creator",
4133
4200
  "over_three_months_late.[].assignees.[]",
4201
+ "over_three_months_late.[].completion.creator",
4134
4202
  "over_three_months_late.[].completion_subscribers.[]",
4135
4203
  "over_three_months_late.[].creator",
4136
4204
  "over_three_months_late.[].steps.[].assignees.[]",
4137
4205
  "over_three_months_late.[].steps.[].completer",
4206
+ "over_three_months_late.[].steps.[].completion.creator",
4138
4207
  "over_three_months_late.[].steps.[].creator",
4139
4208
  "under_a_week_late.[].assignees.[]",
4209
+ "under_a_week_late.[].completion.creator",
4140
4210
  "under_a_week_late.[].completion_subscribers.[]",
4141
4211
  "under_a_week_late.[].creator",
4142
4212
  "under_a_week_late.[].steps.[].assignees.[]",
4143
4213
  "under_a_week_late.[].steps.[].completer",
4214
+ "under_a_week_late.[].steps.[].completion.creator",
4144
4215
  "under_a_week_late.[].steps.[].creator"
4145
4216
  ],
4146
4217
  "GetPerson": [
@@ -4196,6 +4267,7 @@
4196
4267
  "GetSubtask": [
4197
4268
  "assignees.[]",
4198
4269
  "completer",
4270
+ "completion.creator",
4199
4271
  "creator"
4200
4272
  ],
4201
4273
  "GetTemplateLibraryCardTables": [
@@ -4230,10 +4302,12 @@
4230
4302
  ],
4231
4303
  "GetTodo": [
4232
4304
  "assignees.[]",
4305
+ "completion.creator",
4233
4306
  "completion_subscribers.[]",
4234
4307
  "creator",
4235
4308
  "steps.[].assignees.[]",
4236
4309
  "steps.[].completer",
4310
+ "steps.[].completion.creator",
4237
4311
  "steps.[].creator"
4238
4312
  ],
4239
4313
  "GetTodolistOrGroup": [
@@ -4274,10 +4348,12 @@
4274
4348
  "ListCards": [
4275
4349
  "[].assignees.[]",
4276
4350
  "[].completer",
4351
+ "[].completion.creator",
4277
4352
  "[].completion_subscribers.[]",
4278
4353
  "[].creator",
4279
4354
  "[].steps.[].assignees.[]",
4280
4355
  "[].steps.[].completer",
4356
+ "[].steps.[].completion.creator",
4281
4357
  "[].steps.[].creator"
4282
4358
  ],
4283
4359
  "ListClientApprovals": [
@@ -4353,6 +4429,7 @@
4353
4429
  "ListSubtasks": [
4354
4430
  "[].assignees.[]",
4355
4431
  "[].completer",
4432
+ "[].completion.creator",
4356
4433
  "[].creator"
4357
4434
  ],
4358
4435
  "ListTodolistGroups": [
@@ -4363,10 +4440,12 @@
4363
4440
  ],
4364
4441
  "ListTodos": [
4365
4442
  "[].assignees.[]",
4443
+ "[].completion.creator",
4366
4444
  "[].completion_subscribers.[]",
4367
4445
  "[].creator",
4368
4446
  "[].steps.[].assignees.[]",
4369
4447
  "[].steps.[].completer",
4448
+ "[].steps.[].completion.creator",
4370
4449
  "[].steps.[].creator"
4371
4450
  ],
4372
4451
  "ListUploadVersions": [
@@ -4392,10 +4471,12 @@
4392
4471
  ],
4393
4472
  "ReplaceTodo": [
4394
4473
  "assignees.[]",
4474
+ "completion.creator",
4395
4475
  "completion_subscribers.[]",
4396
4476
  "creator",
4397
4477
  "steps.[].assignees.[]",
4398
4478
  "steps.[].completer",
4479
+ "steps.[].completion.creator",
4399
4480
  "steps.[].creator"
4400
4481
  ],
4401
4482
  "Search": [
@@ -4409,6 +4490,7 @@
4409
4490
  "SetCardStepCompletion": [
4410
4491
  "assignees.[]",
4411
4492
  "completer",
4493
+ "completion.creator",
4412
4494
  "creator"
4413
4495
  ],
4414
4496
  "SetClientVisibility": [
@@ -4426,10 +4508,12 @@
4426
4508
  "UpdateCard": [
4427
4509
  "assignees.[]",
4428
4510
  "completer",
4511
+ "completion.creator",
4429
4512
  "completion_subscribers.[]",
4430
4513
  "creator",
4431
4514
  "steps.[].assignees.[]",
4432
4515
  "steps.[].completer",
4516
+ "steps.[].completion.creator",
4433
4517
  "steps.[].creator"
4434
4518
  ],
4435
4519
  "UpdateCardColumn": [
@@ -4439,6 +4523,7 @@
4439
4523
  "UpdateCardStep": [
4440
4524
  "assignees.[]",
4441
4525
  "completer",
4526
+ "completion.creator",
4442
4527
  "creator"
4443
4528
  ],
4444
4529
  "UpdateCloudFile": [
@@ -4476,6 +4561,7 @@
4476
4561
  "UpdateSubtask": [
4477
4562
  "assignees.[]",
4478
4563
  "completer",
4564
+ "completion.creator",
4479
4565
  "creator"
4480
4566
  ],
4481
4567
  "UpdateTimesheetEntry": [
@@ -2,6 +2,7 @@
2
2
 
3
3
  require "cgi/escape"
4
4
  require "securerandom"
5
+ require "uri"
5
6
 
6
7
  module Basecamp
7
8
  module Services
@@ -213,10 +214,13 @@ module Basecamp
213
214
  # @param filename [String] display filename
214
215
  # @param content_type [String] MIME type
215
216
  # @param field [String] form field name
216
- def http_put_multipart(path, io:, filename:, content_type:, field: "file")
217
+ # @param params [Hash] query parameters; nil values are omitted
218
+ def http_put_multipart(path, io:, filename:, content_type:, field: "file", params: {})
217
219
  boundary = "BasecampSDK#{SecureRandom.hex(16)}"
218
220
  body = build_multipart_body(boundary: boundary, field: field, io: io, \
219
221
  filename: filename, content_type: content_type)
222
+ query = URI.encode_www_form(params.compact)
223
+ path = "#{path}?#{query}" unless query.empty?
220
224
  http_put_raw(path, body: body, content_type: "multipart/form-data; boundary=#{boundary}")
221
225
  nil
222
226
  end
@@ -52,10 +52,12 @@ module Basecamp
52
52
  # @param description [String, nil] description
53
53
  # @param admissions [String, nil] invite|employee|team
54
54
  # @param schedule_attributes [Hash, nil] schedule attributes
55
+ # @param wallpaper_mode [String, nil] How the project's wallpaper is laid out. Changes only the layout of a
56
+ # wallpaper already attached; UpdateProjectWallpaper uploads one.
55
57
  # @return [Hash] response data
56
- def update(project_id:, name:, description: nil, admissions: nil, schedule_attributes: nil)
58
+ def update(project_id:, name:, description: nil, admissions: nil, schedule_attributes: nil, wallpaper_mode: nil)
57
59
  with_operation(service: "projects", operation: "update", is_mutation: true, project_id: project_id) do
58
- http_put("/projects/#{project_id}", body: compact_params(name: name, description: description, admissions: admissions, schedule_attributes: schedule_attributes)).json(operation: "UpdateProject")
60
+ http_put("/projects/#{project_id}", body: compact_params(name: name, description: description, admissions: admissions, schedule_attributes: schedule_attributes, wallpaper_mode: wallpaper_mode)).json(operation: "UpdateProject")
59
61
  end
60
62
  end
61
63
 
@@ -98,6 +100,30 @@ module Basecamp
98
100
  nil
99
101
  end
100
102
  end
103
+
104
+ # Upload or replace the project's wallpaper (returns 204 No Content).
105
+ # @param project_id [Integer] project id ID
106
+ # @param io [IO, String] File data to upload (IO object or string)
107
+ # @param filename [String] Display name for the uploaded file
108
+ # @param content_type [String] MIME type of the file (e.g., "image/png")
109
+ # @param mode [String, nil] How the wallpaper is laid out. Omitted, the project's current mode is kept.
110
+ # @return [void]
111
+ def update_project_wallpaper(project_id:, io:, filename:, content_type:, mode: nil)
112
+ with_operation(service: "projects", operation: "update_project_wallpaper", is_mutation: true, project_id: project_id) do
113
+ http_put_multipart("/projects/#{project_id}/wallpaper.json", io: io, filename: filename, content_type: content_type, field: "wallpaper", params: compact_query_params(mode: mode))
114
+ nil
115
+ end
116
+ end
117
+
118
+ # Remove the project's wallpaper (returns 204 No Content).
119
+ # @param project_id [Integer] project id ID
120
+ # @return [void]
121
+ def remove_project_wallpaper(project_id:)
122
+ with_operation(service: "projects", operation: "remove_project_wallpaper", is_mutation: true, project_id: project_id) do
123
+ http_delete("/projects/#{project_id}/wallpaper.json")
124
+ nil
125
+ end
126
+ end
101
127
  end
102
128
  end
103
129
  end
@@ -38,7 +38,7 @@ module Basecamp
38
38
  end
39
39
  end
40
40
 
41
- # Delete a tool (trash it)
41
+ # Remove a tool from the dock: deletes an external link or an empty extra tool, and disables any other tool (returns 204 No Content either way).
42
42
  # @param tool_id [Integer] tool id ID
43
43
  # @return [void]
44
44
  def delete(tool_id:)
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  # Auto-generated from OpenAPI spec. Do not edit manually.
4
- # Generated: 2026-10-20T15:47:49Z
4
+ # Generated: 2026-10-23T22:09:29Z
5
5
 
6
6
  require "json"
7
7
  require "time"
@@ -594,7 +594,11 @@ module Basecamp
594
594
  # Card
595
595
  class Card
596
596
  include TypeHelpers
597
- attr_accessor :app_url, :bucket, :created_at, :creator, :description_attachments, :id, :inherits_status, :parent, :status, :title, :type, :updated_at, :url, :visible_to_clients, :assignees, :bookmark_url, :boosts_count, :boosts_url, :comments_count, :comments_url, :completed, :completed_at, :completer, :completion_subscribers, :completion_url, :content, :description, :due_on, :position, :steps, :subscription_url, :subtasks_completed_count, :subtasks_count, :subtasks_url
597
+ # @!attribute [rw] completed_at
598
+ # @deprecated This shape is deprecated since 2026-10: Never sent by Basecamp; read completion.created_at instead
599
+ # @!attribute [rw] completer
600
+ # @deprecated This shape is deprecated since 2026-10: Never sent by Basecamp; read completion.creator instead
601
+ attr_accessor :app_url, :bucket, :created_at, :creator, :description_attachments, :id, :inherits_status, :parent, :status, :title, :type, :updated_at, :url, :visible_to_clients, :assignees, :bookmark_url, :boosts_count, :boosts_url, :comments_count, :comments_url, :completed, :completed_at, :completer, :completion, :completion_subscribers, :completion_url, :content, :description, :due_on, :position, :steps, :subscription_url, :subtasks_completed_count, :subtasks_count, :subtasks_url
598
602
 
599
603
  # @return [Array<Symbol>]
600
604
  def self.required_fields
@@ -625,6 +629,7 @@ module Basecamp
625
629
  @completed = parse_boolean(data["completed"])
626
630
  @completed_at = parse_datetime(data["completed_at"])
627
631
  @completer = parse_type(data["completer"], "Person")
632
+ @completion = parse_type(data["completion"], "RecordingCompletion")
628
633
  @completion_subscribers = parse_array(data["completion_subscribers"], "Person")
629
634
  @completion_url = data["completion_url"]
630
635
  @content = data["content"]
@@ -663,6 +668,7 @@ module Basecamp
663
668
  "completed" => @completed,
664
669
  "completed_at" => @completed_at,
665
670
  "completer" => @completer,
671
+ "completion" => @completion,
666
672
  "completion_subscribers" => @completion_subscribers,
667
673
  "completion_url" => @completion_url,
668
674
  "content" => @content,
@@ -3414,7 +3420,7 @@ module Basecamp
3414
3420
  include TypeHelpers
3415
3421
  # @!attribute [rw] clientside
3416
3422
  # @deprecated This shape is deprecated since 2024-01: Use Client Visibility feature instead
3417
- attr_accessor :app_url, :created_at, :id, :name, :status, :updated_at, :url, :bookmark_url, :bookmarked, :client_company, :clients_enabled, :clientside, :description, :dock, :end_date, :purpose, :star_url, :starred, :start_date, :timesheet_enabled
3423
+ attr_accessor :app_url, :created_at, :id, :name, :status, :updated_at, :url, :bookmark_url, :bookmarked, :client_company, :clients_enabled, :clientside, :description, :dock, :end_date, :purpose, :star_url, :starred, :start_date, :timesheet_enabled, :wallpaper
3418
3424
 
3419
3425
  # @return [Array<Symbol>]
3420
3426
  def self.required_fields
@@ -3442,6 +3448,7 @@ module Basecamp
3442
3448
  @starred = parse_boolean(data["starred"])
3443
3449
  @start_date = data["start_date"]
3444
3450
  @timesheet_enabled = parse_boolean(data["timesheet_enabled"])
3451
+ @wallpaper = parse_type(data["wallpaper"], "ProjectWallpaper")
3445
3452
  end
3446
3453
 
3447
3454
  def to_h
@@ -3466,6 +3473,7 @@ module Basecamp
3466
3473
  "starred" => @starred,
3467
3474
  "start_date" => @start_date,
3468
3475
  "timesheet_enabled" => @timesheet_enabled,
3476
+ "wallpaper" => @wallpaper,
3469
3477
  }.compact
3470
3478
  end
3471
3479
 
@@ -3581,6 +3589,33 @@ module Basecamp
3581
3589
  end
3582
3590
  end
3583
3591
 
3592
+ # ProjectWallpaper
3593
+ class ProjectWallpaper
3594
+ include TypeHelpers
3595
+ attr_accessor :mode, :url
3596
+
3597
+ # @return [Array<Symbol>]
3598
+ def self.required_fields
3599
+ %i[mode url].freeze
3600
+ end
3601
+
3602
+ def initialize(data = {})
3603
+ @mode = data["mode"]
3604
+ @url = data["url"]
3605
+ end
3606
+
3607
+ def to_h
3608
+ {
3609
+ "mode" => @mode,
3610
+ "url" => @url,
3611
+ }.compact
3612
+ end
3613
+
3614
+ def to_json(*args)
3615
+ to_h.to_json(*args)
3616
+ end
3617
+ end
3618
+
3584
3619
  # Question
3585
3620
  class Question
3586
3621
  include TypeHelpers
@@ -4059,6 +4094,33 @@ module Basecamp
4059
4094
  end
4060
4095
  end
4061
4096
 
4097
+ # RecordingCompletion
4098
+ class RecordingCompletion
4099
+ include TypeHelpers
4100
+ attr_accessor :created_at, :creator
4101
+
4102
+ # @return [Array<Symbol>]
4103
+ def self.required_fields
4104
+ %i[created_at creator].freeze
4105
+ end
4106
+
4107
+ def initialize(data = {})
4108
+ @created_at = parse_datetime(data["created_at"])
4109
+ @creator = parse_type(data["creator"], "Person")
4110
+ end
4111
+
4112
+ def to_h
4113
+ {
4114
+ "created_at" => @created_at,
4115
+ "creator" => @creator,
4116
+ }.compact
4117
+ end
4118
+
4119
+ def to_json(*args)
4120
+ to_h.to_json(*args)
4121
+ end
4122
+ end
4123
+
4062
4124
  # RecordingParent
4063
4125
  class RecordingParent
4064
4126
  include TypeHelpers
@@ -4563,7 +4625,11 @@ module Basecamp
4563
4625
  # Subtask
4564
4626
  class Subtask
4565
4627
  include TypeHelpers
4566
- attr_accessor :app_url, :bucket, :created_at, :creator, :id, :inherits_status, :parent, :status, :title, :type, :updated_at, :url, :visible_to_clients, :assignees, :bookmark_url, :completed, :completed_at, :completer, :completion_url, :due_on, :position
4628
+ # @!attribute [rw] completed_at
4629
+ # @deprecated This shape is deprecated since 2026-10: Never sent by Basecamp; read completion.created_at instead
4630
+ # @!attribute [rw] completer
4631
+ # @deprecated This shape is deprecated since 2026-10: Never sent by Basecamp; read completion.creator instead
4632
+ attr_accessor :app_url, :bucket, :created_at, :creator, :id, :inherits_status, :parent, :status, :title, :type, :updated_at, :url, :visible_to_clients, :assignees, :bookmark_url, :completed, :completed_at, :completer, :completion, :completion_url, :due_on, :position
4567
4633
 
4568
4634
  # @return [Array<Symbol>]
4569
4635
  def self.required_fields
@@ -4589,6 +4655,7 @@ module Basecamp
4589
4655
  @completed = parse_boolean(data["completed"])
4590
4656
  @completed_at = parse_datetime(data["completed_at"])
4591
4657
  @completer = parse_type(data["completer"], "Person")
4658
+ @completion = parse_type(data["completion"], "RecordingCompletion")
4592
4659
  @completion_url = data["completion_url"]
4593
4660
  @due_on = data["due_on"]
4594
4661
  @position = parse_integer(data["position"])
@@ -4614,6 +4681,7 @@ module Basecamp
4614
4681
  "completed" => @completed,
4615
4682
  "completed_at" => @completed_at,
4616
4683
  "completer" => @completer,
4684
+ "completion" => @completion,
4617
4685
  "completion_url" => @completion_url,
4618
4686
  "due_on" => @due_on,
4619
4687
  "position" => @position,
@@ -5056,7 +5124,7 @@ module Basecamp
5056
5124
  # Todo
5057
5125
  class Todo
5058
5126
  include TypeHelpers
5059
- attr_accessor :app_url, :bucket, :content, :created_at, :creator, :description_attachments, :id, :inherits_status, :parent, :status, :title, :type, :updated_at, :url, :visible_to_clients, :assignees, :bookmark_url, :boosts_count, :boosts_url, :comments_count, :comments_url, :completed, :completion_subscribers, :completion_url, :description, :due_on, :position, :starts_on, :steps, :subscription_url, :subtasks_completed_count, :subtasks_count, :subtasks_url
5127
+ attr_accessor :app_url, :bucket, :content, :created_at, :creator, :description_attachments, :id, :inherits_status, :parent, :status, :title, :type, :updated_at, :url, :visible_to_clients, :assignees, :bookmark_url, :boosts_count, :boosts_url, :comments_count, :comments_url, :completed, :completion, :completion_subscribers, :completion_url, :description, :due_on, :position, :starts_on, :steps, :subscription_url, :subtasks_completed_count, :subtasks_count, :subtasks_url
5060
5128
 
5061
5129
  # @return [Array<Symbol>]
5062
5130
  def self.required_fields
@@ -5086,6 +5154,7 @@ module Basecamp
5086
5154
  @comments_count = parse_integer(data["comments_count"])
5087
5155
  @comments_url = data["comments_url"]
5088
5156
  @completed = parse_boolean(data["completed"])
5157
+ @completion = parse_type(data["completion"], "RecordingCompletion")
5089
5158
  @completion_subscribers = parse_array(data["completion_subscribers"], "Person")
5090
5159
  @completion_url = data["completion_url"]
5091
5160
  @description = data["description"]
@@ -5123,6 +5192,7 @@ module Basecamp
5123
5192
  "comments_count" => @comments_count,
5124
5193
  "comments_url" => @comments_url,
5125
5194
  "completed" => @completed,
5195
+ "completion" => @completion,
5126
5196
  "completion_subscribers" => @completion_subscribers,
5127
5197
  "completion_url" => @completion_url,
5128
5198
  "description" => @description,
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Basecamp
4
- VERSION = "0.27.0"
4
+ VERSION = "0.28.0"
5
5
  API_VERSION = "2026-10-19"
6
6
  end
@@ -983,8 +983,13 @@ class ServiceGenerator
983
983
 
984
984
  if op[:has_multipart_body]
985
985
  field = op[:multipart_field] || 'file'
986
+ params_arg = ''
987
+ if op[:query_params].any?
988
+ param_names = op[:query_params].map { |q| "#{to_snake_case(q[:name])}: #{to_snake_case(q[:name])}" }
989
+ params_arg = ", params: compact_query_params(#{param_names.join(', ')})"
990
+ end
986
991
  lines << " http_#{http_method}_multipart(#{path_expr}, io: io, filename: filename, " \
987
- "content_type: content_type, field: \"#{field}\")"
992
+ "content_type: content_type, field: \"#{field}\"#{params_arg})"
988
993
  elsif op[:has_body]
989
994
  body_expr = build_body_expression(op)
990
995
  lines << " http_#{http_method}(#{path_expr}, body: #{body_expr})"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: basecamp-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.27.0
4
+ version: 0.28.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Basecamp
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-21 00:00:00.000000000 Z
11
+ date: 2026-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday