basecamp-sdk 0.29.1 → 0.30.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: 2620bd46c1b588d530b251109f21d2f87582d14fc9e4267c2fa79a28a8807dc4
4
- data.tar.gz: f0dfcbeeacb7841d620fe75e2e41b7b293b31041c819a13cf9c6d10a4c4558eb
3
+ metadata.gz: ddaec5e8714ed7b9f89ba3eee0ffae9f2308b5459c356259d845b3d12337dfb1
4
+ data.tar.gz: '091928234df661ad893075b500d9501dcce44da5f68713a8e0161466fcf59a10'
5
5
  SHA512:
6
- metadata.gz: adb8b91c0ef6d776e47bd9b2afe8109bbc9763d15eabbfc09c6fcba82a091b2513d722c923998cbcdbc8a052e3d5ec9e0e654b9dc76b6ca4595ca1049b9b41b9
7
- data.tar.gz: 583fceab505a1ee471ba68e5baaa830b17bb1c6f75552c49550bf6126cc34f76ea5a02d32ee4cf3f493c454c1a8b8827182657e9119976eabb94ca0b4d0f7fb2
6
+ metadata.gz: 9e30f6a63f2d13cc14c8252efe1912451c0ee19a48b5c59d2c1299ee6527940474c0e0e4f3ea62c5f62a818d03aca0aa9cd2984247ac034522cc8231cc67f597
7
+ data.tar.gz: '0982175e0dd9119091454ee6b30be5c74c5fe276022220e8079a6d88fb73e81e411ceaf414181f612e4f39085dd914b269e4c1dea68374cd1aad3f05b1149180'
data/README.md CHANGED
@@ -320,7 +320,7 @@ The SDK provides the full account-scoped service set documented in SPEC §5. The
320
320
 
321
321
  | Service | Description |
322
322
  |---------|-------------|
323
- | `projects` | Project management |
323
+ | `projects` | Project management, [logo upload and removal](../PROJECT-LOGOS.md) |
324
324
  | `todos` | Todo items |
325
325
  | `todolists` | Todo lists |
326
326
  | `todosets` | Todo set containers |
@@ -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-23T22:09:28Z",
4
+ "generated": "2026-10-27T18:50:42Z",
5
5
  "operations": {
6
6
  "GetAccount": {
7
7
  "retry": {
@@ -1203,6 +1203,17 @@
1203
1203
  "maxPageSize": 50
1204
1204
  }
1205
1205
  },
1206
+ "GetFiling": {
1207
+ "retry": {
1208
+ "maxAttempts": 3,
1209
+ "baseDelayMs": 1000,
1210
+ "backoff": "exponential",
1211
+ "retryOn": [
1212
+ 429,
1213
+ 503
1214
+ ]
1215
+ }
1216
+ },
1206
1217
  "GetEverythingForwards": {
1207
1218
  "retry": {
1208
1219
  "maxAttempts": 3,
@@ -1952,6 +1963,34 @@
1952
1963
  ]
1953
1964
  }
1954
1965
  },
1966
+ "UpdateProjectLogo": {
1967
+ "retry": {
1968
+ "maxAttempts": 3,
1969
+ "baseDelayMs": 1000,
1970
+ "backoff": "exponential",
1971
+ "retryOn": [
1972
+ 429,
1973
+ 503
1974
+ ]
1975
+ },
1976
+ "idempotent": {
1977
+ "natural": true
1978
+ }
1979
+ },
1980
+ "RemoveProjectLogo": {
1981
+ "retry": {
1982
+ "maxAttempts": 3,
1983
+ "baseDelayMs": 1000,
1984
+ "backoff": "exponential",
1985
+ "retryOn": [
1986
+ 429,
1987
+ 503
1988
+ ]
1989
+ },
1990
+ "idempotent": {
1991
+ "natural": true
1992
+ }
1993
+ },
1955
1994
  "ListProjectPeople": {
1956
1995
  "retry": {
1957
1996
  "maxAttempts": 3,
@@ -2444,6 +2483,17 @@
2444
2483
  ]
2445
2484
  }
2446
2485
  },
2486
+ "CopyRecording": {
2487
+ "retry": {
2488
+ "maxAttempts": 2,
2489
+ "baseDelayMs": 1000,
2490
+ "backoff": "exponential",
2491
+ "retryOn": [
2492
+ 429,
2493
+ 503
2494
+ ]
2495
+ }
2496
+ },
2447
2497
  "ListEvents": {
2448
2498
  "retry": {
2449
2499
  "maxAttempts": 3,
@@ -2498,6 +2548,17 @@
2498
2548
  ]
2499
2549
  }
2500
2550
  },
2551
+ "MoveRecording": {
2552
+ "retry": {
2553
+ "maxAttempts": 2,
2554
+ "baseDelayMs": 1000,
2555
+ "backoff": "exponential",
2556
+ "retryOn": [
2557
+ 429,
2558
+ 503
2559
+ ]
2560
+ }
2561
+ },
2501
2562
  "SpotlightRecording": {
2502
2563
  "retry": {
2503
2564
  "maxAttempts": 3,
@@ -71,6 +71,29 @@ module Basecamp
71
71
  end
72
72
  end
73
73
 
74
+ # Upload or replace the project's logo (returns 204 No Content).
75
+ # @param project_id [Integer] project id ID
76
+ # @param io [IO, String] File data to upload (IO object or string)
77
+ # @param filename [String] Display name for the uploaded file
78
+ # @param content_type [String] MIME type of the file (e.g., "image/png")
79
+ # @return [void]
80
+ def update_project_logo(project_id:, io:, filename:, content_type:)
81
+ with_operation(service: "projects", operation: "update_project_logo", is_mutation: true, project_id: project_id) do
82
+ http_put_multipart("/projects/#{project_id}/logo.json", io: io, filename: filename, content_type: content_type, field: "logo")
83
+ nil
84
+ end
85
+ end
86
+
87
+ # Remove the project's logo (returns 204 even when absent). Wallpaper is unchanged.
88
+ # @param project_id [Integer] project id ID
89
+ # @return [void]
90
+ def remove_project_logo(project_id:)
91
+ with_operation(service: "projects", operation: "remove_project_logo", is_mutation: true, project_id: project_id) do
92
+ http_delete("/projects/#{project_id}/logo.json")
93
+ nil
94
+ end
95
+ end
96
+
74
97
  # Record that the current user visited a project, moving it to the front of ListRecentProjects (returns 204 No Content).
75
98
  # @param project_id [Integer] project id ID
76
99
  # @return [void]
@@ -7,6 +7,15 @@ module Basecamp
7
7
  # @generated from OpenAPI spec
8
8
  class RecordingsService < BaseService
9
9
 
10
+ # Get the state of a move or copy started by MoveRecording or CopyRecording.
11
+ # @param filing_id [Integer] filing id ID
12
+ # @return [Hash] response data
13
+ def get_filing(filing_id:)
14
+ with_operation(service: "recordings", operation: "get_filing", is_mutation: false, resource_id: filing_id) do
15
+ http_get("/filings/#{filing_id}", operation: "GetFiling").json(operation: "GetFiling")
16
+ end
17
+ end
18
+
10
19
  # List recordings of a given type across projects
11
20
  # @param type [String] Comment|Document|Door|Kanban::Card|Kanban::Step|Message|Question::Answer|Schedule::Entry|Todo|Todolist|Upload|Vault
12
21
  # @param bucket [String, nil] bucket
@@ -23,6 +32,23 @@ module Basecamp
23
32
  end
24
33
  end
25
34
 
35
+ # Start copying a recording into another project; poll GetFiling for the result.
36
+ # @param recording_id [Integer] recording id ID
37
+ # @param filing_destination_id [Integer, nil] The container to copy into, from the destination project's dock: a card
38
+ # table for a card, a message board for a message, a vault for a document,
39
+ # upload or folder, a schedule for a schedule entry. Give this or
40
+ # destination_project_id.
41
+ # @param destination_project_id [Integer, nil] The project to copy a dock tool to. Applies to tools only, and wins over
42
+ # filing_destination_id when a request for a tool gives both.
43
+ # @param parent_id [Integer, nil] When copying into a vault, a folder inside it to put the copy in.
44
+ # @param include_comments [Boolean, nil] Copy the recording's comments too. Defaults to false.
45
+ # @return [Hash] response data
46
+ def copy(recording_id:, filing_destination_id: nil, destination_project_id: nil, parent_id: nil, include_comments: nil)
47
+ with_operation(service: "recordings", operation: "copy", is_mutation: true, resource_id: recording_id) do
48
+ http_post("/recordings/#{recording_id}/copies.json", body: compact_params(filing_destination_id: filing_destination_id, destination_project_id: destination_project_id, parent_id: parent_id, include_comments: include_comments)).json(operation: "CopyRecording")
49
+ end
50
+ end
51
+
26
52
  # Move a document, upload or vault into another vault in its project, or reorder it in its own vault.
27
53
  # @param recording_id [Integer] recording id ID
28
54
  # @param parent_id [Integer] The destination vault. The recording's current vault keeps it where it is
@@ -37,6 +63,22 @@ module Basecamp
37
63
  end
38
64
  end
39
65
 
66
+ # Start moving a recording into another project; poll GetFiling for the result.
67
+ # @param recording_id [Integer] recording id ID
68
+ # @param filing_destination_id [Integer, nil] The container to move into, from the destination project's dock: a card
69
+ # table for a card, a message board for a message, a vault for a document,
70
+ # upload or folder, a schedule for a schedule entry. Give this or
71
+ # destination_project_id.
72
+ # @param destination_project_id [Integer, nil] The project to move a dock tool to. Applies to tools only, and wins over
73
+ # filing_destination_id when a request for a tool gives both.
74
+ # @param parent_id [Integer, nil] When moving into a vault, a folder inside it to put the recording in.
75
+ # @return [Hash] response data
76
+ def move(recording_id:, filing_destination_id: nil, destination_project_id: nil, parent_id: nil)
77
+ with_operation(service: "recordings", operation: "move", is_mutation: true, resource_id: recording_id) do
78
+ http_post("/recordings/#{recording_id}/moves.json", body: compact_params(filing_destination_id: filing_destination_id, destination_project_id: destination_project_id, parent_id: parent_id)).json(operation: "MoveRecording")
79
+ end
80
+ end
81
+
40
82
  # Put a recording's card in the spotlight area on its project or template home page.
41
83
  # @param recording_id [Integer] recording id ID
42
84
  # @return [Hash] response data
@@ -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-23T22:09:29Z
4
+ # Generated: 2026-10-27T18:50:42Z
5
5
 
6
6
  require "json"
7
7
  require "time"
@@ -1943,6 +1943,72 @@ module Basecamp
1943
1943
  end
1944
1944
  end
1945
1945
 
1946
+ # Filing
1947
+ class Filing
1948
+ include TypeHelpers
1949
+ attr_accessor :id, :source_recording_id, :status, :type, :url, :destination_recording
1950
+
1951
+ # @return [Array<Symbol>]
1952
+ def self.required_fields
1953
+ %i[id source_recording_id status type url].freeze
1954
+ end
1955
+
1956
+ def initialize(data = {})
1957
+ @id = parse_integer(data["id"])
1958
+ @source_recording_id = parse_integer(data["source_recording_id"])
1959
+ @status = data["status"]
1960
+ @type = data["type"]
1961
+ @url = data["url"]
1962
+ @destination_recording = parse_type(data["destination_recording"], "FilingDestinationRecording")
1963
+ end
1964
+
1965
+ def to_h
1966
+ {
1967
+ "id" => @id,
1968
+ "source_recording_id" => @source_recording_id,
1969
+ "status" => @status,
1970
+ "type" => @type,
1971
+ "url" => @url,
1972
+ "destination_recording" => @destination_recording,
1973
+ }.compact
1974
+ end
1975
+
1976
+ def to_json(*args)
1977
+ to_h.to_json(*args)
1978
+ end
1979
+ end
1980
+
1981
+ # FilingDestinationRecording
1982
+ class FilingDestinationRecording
1983
+ include TypeHelpers
1984
+ attr_accessor :app_url, :id, :type, :url
1985
+
1986
+ # @return [Array<Symbol>]
1987
+ def self.required_fields
1988
+ %i[app_url id type url].freeze
1989
+ end
1990
+
1991
+ def initialize(data = {})
1992
+ @app_url = data["app_url"]
1993
+ @id = parse_integer(data["id"])
1994
+ @type = data["type"]
1995
+ @url = data["url"]
1996
+ end
1997
+
1998
+ def to_h
1999
+ {
2000
+ "app_url" => @app_url,
2001
+ "id" => @id,
2002
+ "type" => @type,
2003
+ "url" => @url,
2004
+ }.compact
2005
+ end
2006
+
2007
+ def to_json(*args)
2008
+ to_h.to_json(*args)
2009
+ end
2010
+ end
2011
+
1946
2012
  # Folder
1947
2013
  class Folder
1948
2014
  include TypeHelpers
@@ -3420,7 +3486,7 @@ module Basecamp
3420
3486
  include TypeHelpers
3421
3487
  # @!attribute [rw] clientside
3422
3488
  # @deprecated This shape is deprecated since 2024-01: Use Client Visibility feature instead
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
3489
+ attr_accessor :app_url, :created_at, :id, :name, :status, :updated_at, :url, :bookmark_url, :bookmarked, :client_company, :clients_enabled, :clientside, :description, :dock, :end_date, :logo, :purpose, :star_url, :starred, :start_date, :timesheet_enabled, :wallpaper
3424
3490
 
3425
3491
  # @return [Array<Symbol>]
3426
3492
  def self.required_fields
@@ -3443,6 +3509,7 @@ module Basecamp
3443
3509
  @description = data["description"]
3444
3510
  @dock = parse_array(data["dock"], "DockItem")
3445
3511
  @end_date = data["end_date"]
3512
+ @logo = parse_type(data["logo"], "ProjectLogo")
3446
3513
  @purpose = data["purpose"]
3447
3514
  @star_url = data["star_url"]
3448
3515
  @starred = parse_boolean(data["starred"])
@@ -3468,6 +3535,7 @@ module Basecamp
3468
3535
  "description" => @description,
3469
3536
  "dock" => @dock,
3470
3537
  "end_date" => @end_date,
3538
+ "logo" => @logo,
3471
3539
  "purpose" => @purpose,
3472
3540
  "star_url" => @star_url,
3473
3541
  "starred" => @starred,
@@ -3589,6 +3657,31 @@ module Basecamp
3589
3657
  end
3590
3658
  end
3591
3659
 
3660
+ # ProjectLogo
3661
+ class ProjectLogo
3662
+ include TypeHelpers
3663
+ attr_accessor :url
3664
+
3665
+ # @return [Array<Symbol>]
3666
+ def self.required_fields
3667
+ %i[url].freeze
3668
+ end
3669
+
3670
+ def initialize(data = {})
3671
+ @url = data["url"]
3672
+ end
3673
+
3674
+ def to_h
3675
+ {
3676
+ "url" => @url,
3677
+ }.compact
3678
+ end
3679
+
3680
+ def to_json(*args)
3681
+ to_h.to_json(*args)
3682
+ end
3683
+ end
3684
+
3592
3685
  # ProjectWallpaper
3593
3686
  class ProjectWallpaper
3594
3687
  include TypeHelpers
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Basecamp
4
- VERSION = "0.29.1"
4
+ VERSION = "0.30.0"
5
5
  API_VERSION = "2026-10-19"
6
6
  end
@@ -182,6 +182,8 @@ class ServiceGenerator
182
182
  'SpotlightRecording' => 'spotlight',
183
183
  'UnspotlightRecording' => 'unspotlight',
184
184
  'MoveRecordingToVault' => 'move_to_vault',
185
+ 'CopyRecording' => 'copy',
186
+ 'GetFiling' => 'get_filing',
185
187
  'GetMyProfile' => 'my_profile',
186
188
  'GetTodolistOrGroup' => 'get',
187
189
  # The plain `update` name belongs to the merge-safe composite; the raw
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.29.1
4
+ version: 0.30.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-26 00:00:00.000000000 Z
11
+ date: 2026-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday