@37signals/basecamp 0.13.0 → 0.15.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.
Files changed (71) hide show
  1. package/README.md +4 -3
  2. package/dist/client.d.ts +2 -2
  3. package/dist/client.js +2 -2
  4. package/dist/download.d.ts +3 -1
  5. package/dist/download.d.ts.map +1 -1
  6. package/dist/download.js +17 -4
  7. package/dist/download.js.map +1 -1
  8. package/dist/errors.d.ts +27 -1
  9. package/dist/errors.d.ts.map +1 -1
  10. package/dist/errors.js +89 -13
  11. package/dist/errors.js.map +1 -1
  12. package/dist/generated/metadata.d.ts.map +1 -1
  13. package/dist/generated/metadata.js +12 -1
  14. package/dist/generated/metadata.js.map +1 -1
  15. package/dist/generated/metadata.ts +12 -1
  16. package/dist/generated/openapi-stripped.json +559 -30
  17. package/dist/generated/path-mapping.d.ts.map +1 -1
  18. package/dist/generated/path-mapping.js +1 -0
  19. package/dist/generated/path-mapping.js.map +1 -1
  20. package/dist/generated/path-mapping.ts +1 -0
  21. package/dist/generated/schema.d.ts +468 -29
  22. package/dist/generated/services/checkins.d.ts +1 -1
  23. package/dist/generated/services/checkins.d.ts.map +1 -1
  24. package/dist/generated/services/checkins.ts +1 -1
  25. package/dist/generated/services/gauges.d.ts +3 -2
  26. package/dist/generated/services/gauges.d.ts.map +1 -1
  27. package/dist/generated/services/gauges.ts +2 -2
  28. package/dist/generated/services/search.d.ts +2 -1
  29. package/dist/generated/services/search.d.ts.map +1 -1
  30. package/dist/generated/services/search.ts +1 -1
  31. package/dist/generated/services/uploads.d.ts +36 -2
  32. package/dist/generated/services/uploads.d.ts.map +1 -1
  33. package/dist/generated/services/uploads.js +37 -1
  34. package/dist/generated/services/uploads.js.map +1 -1
  35. package/dist/generated/services/uploads.ts +65 -2
  36. package/dist/index.d.ts +1 -1
  37. package/dist/index.d.ts.map +1 -1
  38. package/dist/index.js.map +1 -1
  39. package/dist/oauth/authorization-document.d.ts +208 -0
  40. package/dist/oauth/authorization-document.d.ts.map +1 -0
  41. package/dist/oauth/authorization-document.js +135 -0
  42. package/dist/oauth/authorization-document.js.map +1 -0
  43. package/dist/oauth/identity.d.ts +7 -1
  44. package/dist/oauth/identity.d.ts.map +1 -1
  45. package/dist/oauth/identity.js +8 -19
  46. package/dist/oauth/identity.js.map +1 -1
  47. package/dist/oauth/index.d.ts +1 -0
  48. package/dist/oauth/index.d.ts.map +1 -1
  49. package/dist/oauth/index.js +2 -0
  50. package/dist/oauth/index.js.map +1 -1
  51. package/dist/retry.d.ts +23 -0
  52. package/dist/retry.d.ts.map +1 -1
  53. package/dist/retry.js +45 -10
  54. package/dist/retry.js.map +1 -1
  55. package/dist/services/authorization.d.ts +22 -52
  56. package/dist/services/authorization.d.ts.map +1 -1
  57. package/dist/services/authorization.js +14 -32
  58. package/dist/services/authorization.js.map +1 -1
  59. package/dist/services/base.d.ts +25 -2
  60. package/dist/services/base.d.ts.map +1 -1
  61. package/dist/services/base.js +85 -15
  62. package/dist/services/base.js.map +1 -1
  63. package/package.json +6 -4
  64. package/src/generated/metadata.ts +12 -1
  65. package/src/generated/openapi-stripped.json +559 -30
  66. package/src/generated/path-mapping.ts +1 -0
  67. package/src/generated/schema.d.ts +468 -29
  68. package/src/generated/services/checkins.ts +1 -1
  69. package/src/generated/services/gauges.ts +2 -2
  70. package/src/generated/services/search.ts +1 -1
  71. package/src/generated/services/uploads.ts +65 -2
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "Basecamp",
5
- "version": "2026-08-05",
5
+ "version": "2026-08-11",
6
6
  "description": "Basecamp API",
7
7
  "contact": {
8
8
  "name": "Basecamp",
@@ -417,6 +417,16 @@
417
417
  }
418
418
  }
419
419
  }
420
+ },
421
+ "507": {
422
+ "description": "StorageLimitError 507 response",
423
+ "content": {
424
+ "application/json": {
425
+ "schema": {
426
+ "$ref": "#/components/schemas/StorageLimitErrorResponseContent"
427
+ }
428
+ }
429
+ }
420
430
  }
421
431
  },
422
432
  "tags": [
@@ -6571,6 +6581,16 @@
6571
6581
  }
6572
6582
  }
6573
6583
  }
6584
+ },
6585
+ "507": {
6586
+ "description": "StorageLimitError 507 response",
6587
+ "content": {
6588
+ "application/json": {
6589
+ "schema": {
6590
+ "$ref": "#/components/schemas/StorageLimitErrorResponseContent"
6591
+ }
6592
+ }
6593
+ }
6574
6594
  }
6575
6595
  },
6576
6596
  "tags": [
@@ -22663,6 +22683,125 @@
22663
22683
  503
22664
22684
  ]
22665
22685
  }
22686
+ },
22687
+ "post": {
22688
+ "description": "Replace an upload's file with a new version\n\nThe recording keeps its id, its URL and its comments; the previous file becomes a\npast version. Use this instead of CreateUpload when publishing a new release of the\nsame file, so its published link keeps working.",
22689
+ "operationId": "CreateUploadVersion",
22690
+ "requestBody": {
22691
+ "content": {
22692
+ "application/json": {
22693
+ "schema": {
22694
+ "$ref": "#/components/schemas/CreateUploadVersionRequestContent"
22695
+ }
22696
+ }
22697
+ },
22698
+ "required": true
22699
+ },
22700
+ "parameters": [
22701
+ {
22702
+ "name": "uploadId",
22703
+ "in": "path",
22704
+ "schema": {
22705
+ "type": "integer",
22706
+ "format": "int64"
22707
+ },
22708
+ "required": true
22709
+ }
22710
+ ],
22711
+ "responses": {
22712
+ "201": {
22713
+ "description": "CreateUploadVersion 201 response",
22714
+ "content": {
22715
+ "application/json": {
22716
+ "schema": {
22717
+ "$ref": "#/components/schemas/CreateUploadVersionResponseContent"
22718
+ }
22719
+ }
22720
+ }
22721
+ },
22722
+ "401": {
22723
+ "description": "UnauthorizedError 401 response",
22724
+ "content": {
22725
+ "application/json": {
22726
+ "schema": {
22727
+ "$ref": "#/components/schemas/UnauthorizedErrorResponseContent"
22728
+ }
22729
+ }
22730
+ }
22731
+ },
22732
+ "403": {
22733
+ "description": "ForbiddenError 403 response",
22734
+ "content": {
22735
+ "application/json": {
22736
+ "schema": {
22737
+ "$ref": "#/components/schemas/ForbiddenErrorResponseContent"
22738
+ }
22739
+ }
22740
+ }
22741
+ },
22742
+ "404": {
22743
+ "description": "NotFoundError 404 response",
22744
+ "content": {
22745
+ "application/json": {
22746
+ "schema": {
22747
+ "$ref": "#/components/schemas/NotFoundErrorResponseContent"
22748
+ }
22749
+ }
22750
+ }
22751
+ },
22752
+ "422": {
22753
+ "description": "ValidationError 422 response",
22754
+ "content": {
22755
+ "application/json": {
22756
+ "schema": {
22757
+ "$ref": "#/components/schemas/ValidationErrorResponseContent"
22758
+ }
22759
+ }
22760
+ }
22761
+ },
22762
+ "429": {
22763
+ "description": "RateLimitError 429 response",
22764
+ "content": {
22765
+ "application/json": {
22766
+ "schema": {
22767
+ "$ref": "#/components/schemas/RateLimitErrorResponseContent"
22768
+ }
22769
+ }
22770
+ }
22771
+ },
22772
+ "500": {
22773
+ "description": "InternalServerError 500 response",
22774
+ "content": {
22775
+ "application/json": {
22776
+ "schema": {
22777
+ "$ref": "#/components/schemas/InternalServerErrorResponseContent"
22778
+ }
22779
+ }
22780
+ }
22781
+ },
22782
+ "507": {
22783
+ "description": "StorageLimitError 507 response",
22784
+ "content": {
22785
+ "application/json": {
22786
+ "schema": {
22787
+ "$ref": "#/components/schemas/StorageLimitErrorResponseContent"
22788
+ }
22789
+ }
22790
+ }
22791
+ }
22792
+ },
22793
+ "tags": [
22794
+ "Files"
22795
+ ],
22796
+ "x-basecamp-retry": {
22797
+ "maxAttempts": 2,
22798
+ "baseDelayMs": 1000,
22799
+ "backoff": "exponential",
22800
+ "retryOn": [
22801
+ 429,
22802
+ 503
22803
+ ]
22804
+ }
22666
22805
  }
22667
22806
  },
22668
22807
  "/vaults/{vaultId}": {
@@ -23221,6 +23360,16 @@
23221
23360
  }
23222
23361
  }
23223
23362
  }
23363
+ },
23364
+ "507": {
23365
+ "description": "StorageLimitError 507 response",
23366
+ "content": {
23367
+ "application/json": {
23368
+ "schema": {
23369
+ "$ref": "#/components/schemas/StorageLimitErrorResponseContent"
23370
+ }
23371
+ }
23372
+ }
23224
23373
  }
23225
23374
  },
23226
23375
  "tags": [
@@ -24755,7 +24904,8 @@
24755
24904
  "type": "string"
24756
24905
  },
24757
24906
  "command_url": {
24758
- "type": "string"
24907
+ "type": "string",
24908
+ "description": "Only present when the requester is an account administrator; possession of this URL is enough to command the bot."
24759
24909
  },
24760
24910
  "url": {
24761
24911
  "type": "string"
@@ -24764,7 +24914,8 @@
24764
24914
  "type": "string"
24765
24915
  },
24766
24916
  "lines_url": {
24767
- "type": "string"
24917
+ "type": "string",
24918
+ "description": "Only present when the requester is an account administrator; possession of this URL is enough to post lines as the bot."
24768
24919
  }
24769
24920
  },
24770
24921
  "required": [
@@ -26145,6 +26296,40 @@
26145
26296
  "CreateUploadResponseContent": {
26146
26297
  "$ref": "#/components/schemas/Upload"
26147
26298
  },
26299
+ "CreateUploadVersionRequestContent": {
26300
+ "type": "object",
26301
+ "properties": {
26302
+ "attachable_sgid": {
26303
+ "type": "string"
26304
+ },
26305
+ "base_name": {
26306
+ "type": "string",
26307
+ "description": "Omit to keep the uploaded file's own name. Sending \"\" also keeps it."
26308
+ },
26309
+ "description": {
26310
+ "type": "string",
26311
+ "description": "Presence-aware: omit to carry the previous version's description forward,\nsend \"\" to clear it, send a value to set it."
26312
+ },
26313
+ "notify": {
26314
+ "type": "string",
26315
+ "description": "Who to notify: \"default\", \"everyone\", or \"custom\" (the people in subscriptions).\n\nOmit both this and subscriptions to notify nobody. A subscriptions array sent\nwithout notify is read as \"custom\"."
26316
+ },
26317
+ "subscriptions": {
26318
+ "type": "array",
26319
+ "items": {
26320
+ "type": "integer",
26321
+ "format": "int64"
26322
+ },
26323
+ "description": "People to notify about the replacement and subscribe to the upload."
26324
+ }
26325
+ },
26326
+ "required": [
26327
+ "attachable_sgid"
26328
+ ]
26329
+ },
26330
+ "CreateUploadVersionResponseContent": {
26331
+ "$ref": "#/components/schemas/Upload"
26332
+ },
26148
26333
  "CreateVaultRequestContent": {
26149
26334
  "type": "object",
26150
26335
  "properties": {
@@ -27703,10 +27888,13 @@
27703
27888
  "type": "array",
27704
27889
  "items": {
27705
27890
  "$ref": "#/components/schemas/TimelineEvent"
27706
- },
27707
- "x-go-type-skip-optional-pointer": true
27891
+ }
27708
27892
  }
27709
- }
27893
+ },
27894
+ "required": [
27895
+ "events",
27896
+ "person"
27897
+ ]
27710
27898
  },
27711
27899
  "GetPersonResponseContent": {
27712
27900
  "$ref": "#/components/schemas/Person"
@@ -28359,7 +28547,7 @@
28359
28547
  "ListUploadVersionsResponseContent": {
28360
28548
  "type": "array",
28361
28549
  "items": {
28362
- "$ref": "#/components/schemas/Upload"
28550
+ "$ref": "#/components/schemas/UploadVersion"
28363
28551
  }
28364
28552
  },
28365
28553
  "ListUploadsResponseContent": {
@@ -28728,6 +28916,7 @@
28728
28916
  },
28729
28917
  "MyAssignmentAssignee": {
28730
28918
  "type": "object",
28919
+ "description": "A person as bc3's `people/_person_minimal.json.jbuilder` renders them —\nthe same three-key partial behind UpcomingSchedulePerson and\nOutOfOfficePerson. All three keys are emitted unconditionally, so all\nthree are required.",
28731
28920
  "properties": {
28732
28921
  "id": {
28733
28922
  "type": "integer",
@@ -28743,7 +28932,9 @@
28743
28932
  }
28744
28933
  },
28745
28934
  "required": [
28746
- "id"
28935
+ "avatar_url",
28936
+ "id",
28937
+ "name"
28747
28938
  ]
28748
28939
  },
28749
28940
  "MyAssignmentBucket": {
@@ -29036,6 +29227,7 @@
29036
29227
  },
29037
29228
  "OutOfOfficePerson": {
29038
29229
  "type": "object",
29230
+ "description": "A person as bc3's `people/_person_minimal.json.jbuilder` renders them —\nthe same three-key partial behind UpcomingSchedulePerson and\nMyAssignmentAssignee. All three keys are emitted unconditionally, so all\nthree are required.",
29039
29231
  "properties": {
29040
29232
  "id": {
29041
29233
  "type": "integer",
@@ -29051,7 +29243,9 @@
29051
29243
  }
29052
29244
  },
29053
29245
  "required": [
29054
- "id"
29246
+ "avatar_url",
29247
+ "id",
29248
+ "name"
29055
29249
  ]
29056
29250
  },
29057
29251
  "PauseQuestionResponseContent": {
@@ -30612,9 +30806,11 @@
30612
30806
  },
30613
30807
  "SearchResult": {
30614
30808
  "type": "object",
30809
+ "description": "One hit from account-wide search — a polymorphic projection over every\nsearchable recording type.\n\nMost result types render the common recording envelope\n(`recordings/_recording.json.jbuilder`) plus their own recordable partial,\nbut `api_search_result_template_path` special-cases four branches — chat\nlines, kanban (card table) lists, file attachments and gauge needles — and\nthe file-attachment branch writes its own projection from scratch instead\nof the envelope. Members are therefore optional unless every branch emits\nthem; the doc comments name the branches that carry each optional member.",
30615
30810
  "properties": {
30616
30811
  "id": {
30617
30812
  "type": "integer",
30813
+ "description": "The recording id. Optional only because the file-attachment branch\n(`searches/_attachment.json.jbuilder`) skips the recording envelope and\nemits none of the top-level id/title/type/url/app_url keys; every other\nbranch emits all five.",
30618
30814
  "format": "int64"
30619
30815
  },
30620
30816
  "status": {
@@ -30638,23 +30834,31 @@
30638
30834
  }
30639
30835
  },
30640
30836
  "title": {
30641
- "type": "string"
30837
+ "type": "string",
30838
+ "description": "See `id` — omitted by the file-attachment branch, emitted by every other\nbranch."
30642
30839
  },
30643
30840
  "inherits_status": {
30644
30841
  "type": "boolean"
30645
30842
  },
30646
30843
  "type": {
30647
- "type": "string"
30844
+ "type": "string",
30845
+ "description": "See `id` — omitted by the file-attachment branch, emitted by every other\nbranch. A file-attachment hit is therefore recognizable by the absence\nof this key (its file keys, `filename` through `app_download_url`, are\nthe positive signal)."
30648
30846
  },
30649
30847
  "url": {
30650
- "type": "string"
30848
+ "type": "string",
30849
+ "description": "See `id` — omitted by the file-attachment branch, emitted by every other\nbranch."
30651
30850
  },
30652
30851
  "app_url": {
30653
- "type": "string"
30852
+ "type": "string",
30853
+ "description": "See `id` — omitted by the file-attachment branch, emitted by every other\nbranch."
30654
30854
  },
30655
30855
  "bookmark_url": {
30656
30856
  "type": "string"
30657
30857
  },
30858
+ "subscription_url": {
30859
+ "type": "string",
30860
+ "description": "Subscription URL, emitted by the common recording envelope for any\nsubscribable result — kanban lists and gauge needles among the special\nbranches, plus subscribable generic-branch types (messages, todos, …)."
30861
+ },
30658
30862
  "bubble_up_url": {
30659
30863
  "type": "string",
30660
30864
  "description": "URL of the Bubble Up record for this recording (BC5 addition). Optional\nhere because this is a polymorphic projection:\n`recordings/_recording.json.jbuilder` emits the key only when the caller\npasses `local_assigns[:bubbleupable]`, and `todolists/_todolist` is the\nonly partial that does. So a Todolist-shaped instance carries it and the\nother recording types do not."
@@ -30697,7 +30901,7 @@
30697
30901
  "items": {
30698
30902
  "$ref": "#/components/schemas/RichTextAttachment"
30699
30903
  },
30700
- "description": "Rich-text companion arrays carried through the polymorphic search\nprojection. A given result is one recording type, so it carries only\nthe array matching its rich-text attribute (`content_attachments` for a\nComment/Message, `description_attachments` for a Todo); a webhook-sourced\nresult carries neither. Optional (no `@required`), non-nullable.\n\nSearch results additionally repeat this same array under a generic\n`attachments` key. It is a redundant projection, not a distinct\naggregate: `searches/show.json.jbuilder` emits\n`recording.downloadable_attachments`, which delegates to the recordable's\nsole `rich_text_content`, through the same `attachments/_attachment`\npartial that `recordings/_rich_text.json.jbuilder` uses to build the\ncompanion array. `RichText.rich_text_attribute` permits exactly one\nrich-text attribute per model, so the two keys always carry identical\nelements. Modeling `attachments` would duplicate the field, so it is\ndeliberately not modeled.",
30904
+ "description": "Rich-text companion arrays carried through the polymorphic search\nprojection. A given result is one recording type, so it carries only\nthe array matching its rich-text attribute (`content_attachments` for a\nComment/Message, `description_attachments` for a Todo); a webhook-sourced\nresult carries neither. Optional (no `@required`), non-nullable.",
30701
30905
  "x-go-type-skip-optional-pointer": true
30702
30906
  },
30703
30907
  "description_attachments": {
@@ -30708,18 +30912,219 @@
30708
30912
  "description": "See `content_attachments` — the description-attribute companion array.",
30709
30913
  "x-go-type-skip-optional-pointer": true
30710
30914
  },
30915
+ "attachments": {
30916
+ "type": "array",
30917
+ "items": {
30918
+ "$ref": "#/components/schemas/SearchResultAttachment"
30919
+ },
30920
+ "description": "File attachments on the result, in either of two wire shapes — see\n`SearchResultAttachment`.\n\nFor a result whose recordable carries downloadable rich-text\nattachments, `searches/show.json.jbuilder` emits this key through the\nsame `attachments/_attachment` partial that builds the rich-text\ncompanion array above, so it repeats that array's elements. For a chat\n*upload* line, `chats/lines/_upload.json.jbuilder` instead builds a\nbespoke six-key aggregate inline — and because upload lines have no\nrich-text attribute, the show template never overwrites it, so that\ndistinct shape survives to the wire.",
30921
+ "x-go-type-skip-optional-pointer": true
30922
+ },
30711
30923
  "subject": {
30712
30924
  "type": "string"
30925
+ },
30926
+ "boosts_count": {
30927
+ "type": "integer",
30928
+ "description": "Boost count, emitted by the recording envelope when the branch passes\n`boostable` — chat lines and gauge needles.",
30929
+ "format": "int32"
30930
+ },
30931
+ "boosts_url": {
30932
+ "type": "string",
30933
+ "description": "See `boosts_count` — the companion URL."
30934
+ },
30935
+ "language": {
30936
+ "type": "string",
30937
+ "description": "Language of a code chat line (`chats/lines/_code.json.jbuilder`);\nvalidated present on the model, so never null when the key is emitted."
30938
+ },
30939
+ "image_url": {
30940
+ "type": "string",
30941
+ "description": "Image URL of a soundtracked (play-kind) chat line whose sound carries an\nimage; such a line emits `image_url` in place of `content`."
30942
+ },
30943
+ "sound_url": {
30944
+ "type": "string",
30945
+ "description": "Sound URL of a play-kind chat line; always emitted for that kind."
30946
+ },
30947
+ "subscribers": {
30948
+ "type": "array",
30949
+ "items": {
30950
+ "$ref": "#/components/schemas/Person"
30951
+ },
30952
+ "description": "Everyone subscribed to the kanban list, as full Person projections.",
30953
+ "x-go-type-skip-optional-pointer": true
30954
+ },
30955
+ "color": {
30956
+ "type": "string",
30957
+ "description": "Color of a kanban list or gauge needle. Emitted unconditionally by both\nbranches with a null value when unset, so it is nullable (the enhance\npass layers `nullable: true` onto the OpenAPI).",
30958
+ "nullable": true
30959
+ },
30960
+ "cards_count": {
30961
+ "type": "integer",
30962
+ "description": "Number of cards in the kanban list.",
30963
+ "format": "int32"
30964
+ },
30965
+ "comment_count": {
30966
+ "type": "integer",
30967
+ "description": "Comment count of a kanban list or gauge needle (branch-partial key,\nsingular `comment_count` — distinct from the envelope's\n`comments_count`, which a needle also carries).",
30968
+ "format": "int32"
30969
+ },
30970
+ "cards_url": {
30971
+ "type": "string",
30972
+ "description": "API URL of the kanban list's cards."
30973
+ },
30974
+ "on_hold": {
30975
+ "$ref": "#/components/schemas/CardColumnOnHold"
30976
+ },
30977
+ "comments_count": {
30978
+ "type": "integer",
30979
+ "description": "Comment count, emitted by the recording envelope when the branch passes\n`commentable` — gauge needles among the special branches, plus\ncommentable generic-branch types.",
30980
+ "format": "int32"
30981
+ },
30982
+ "comments_url": {
30983
+ "type": "string",
30984
+ "description": "See `comments_count` — the companion URL."
30985
+ },
30986
+ "position": {
30987
+ "type": "integer",
30988
+ "description": "Position of the result. Two emitters share the key: the recording\nenvelope emits list position for positioned recordings (kanban lists\namong the special branches), and the gauge-needle branch overwrites it\nwith the needle's own 0–100 gauge position.",
30989
+ "format": "int32"
30990
+ },
30991
+ "filename": {
30992
+ "type": "string",
30993
+ "description": "Filename of a file-attachment hit. This and the following file keys are\nemitted only by the file-attachment branch — the one branch that omits\nthe id/title/type/url/app_url envelope keys."
30994
+ },
30995
+ "content_type": {
30996
+ "type": "string",
30997
+ "description": "MIME type of a file-attachment hit."
30998
+ },
30999
+ "byte_size": {
31000
+ "type": "integer",
31001
+ "description": "Size in bytes of a file-attachment hit.",
31002
+ "format": "int64"
31003
+ },
31004
+ "previewable": {
31005
+ "type": "boolean",
31006
+ "description": "Whether the file can be previewed."
31007
+ },
31008
+ "width": {
31009
+ "type": "integer",
31010
+ "description": "Pixel width, emitted only when the file is previewable. May be\nfloat-spelled (`1024.0`) and nullable, like every other blob dimension —\nsee `RichTextAttachment.width` for the cross-SDK typing note.",
31011
+ "format": "int32",
31012
+ "nullable": true,
31013
+ "x-go-type": "types.FlexInt",
31014
+ "x-go-type-import": {
31015
+ "path": "github.com/basecamp/basecamp-sdk/go/pkg/types"
31016
+ }
31017
+ },
31018
+ "height": {
31019
+ "type": "integer",
31020
+ "description": "See `width` — same conditional emission and nullable/float-spelled\nbehavior.",
31021
+ "format": "int32",
31022
+ "nullable": true,
31023
+ "x-go-type": "types.FlexInt",
31024
+ "x-go-type-import": {
31025
+ "path": "github.com/basecamp/basecamp-sdk/go/pkg/types"
31026
+ }
31027
+ },
31028
+ "preview_url": {
31029
+ "type": "string",
31030
+ "description": "Full-size preview URL of a file-attachment hit."
31031
+ },
31032
+ "thumbnail_url": {
31033
+ "type": "string",
31034
+ "description": "Thumbnail URL of a file-attachment hit."
31035
+ },
31036
+ "download_url": {
31037
+ "type": "string",
31038
+ "description": "Authenticated download URL of a file-attachment hit.",
31039
+ "x-basecamp-auth-routable-url": {}
31040
+ },
31041
+ "app_download_url": {
31042
+ "type": "string",
31043
+ "description": "Web (app-host) download URL of a file-attachment hit."
30713
31044
  }
30714
31045
  },
30715
31046
  "required": [
30716
- "app_url",
30717
31047
  "content",
30718
- "description",
30719
- "id",
30720
- "title",
30721
- "type",
30722
- "url"
31048
+ "description"
31049
+ ]
31050
+ },
31051
+ "SearchResultAttachment": {
31052
+ "type": "object",
31053
+ "description": "A file attached to a search result, in either of two wire shapes.\n\nThis is an optional-field superset over the two variants the search\nprojection emits (the TimelineAttachment approach): the rich-text\nattachment/blob shape rendered through `attachments/_attachment` +\n`blobs/_blob` — the same emitters `RichTextAttachment` models — and the\nbespoke six-key aggregate a chat upload line builds inline in\n`chats/lines/_upload.json.jbuilder`. Only the four keys both variants\nalways emit are `@required`; the rest identify their variant.",
31054
+ "properties": {
31055
+ "filename": {
31056
+ "type": "string",
31057
+ "description": "Original filename (both variants)."
31058
+ },
31059
+ "content_type": {
31060
+ "type": "string",
31061
+ "description": "MIME type of the file (both variants)."
31062
+ },
31063
+ "byte_size": {
31064
+ "type": "integer",
31065
+ "description": "Size of the file in bytes (both variants).",
31066
+ "format": "int64"
31067
+ },
31068
+ "download_url": {
31069
+ "type": "string",
31070
+ "description": "Authenticated download URL for the file (both variants).",
31071
+ "x-basecamp-auth-routable-url": {}
31072
+ },
31073
+ "id": {
31074
+ "type": "integer",
31075
+ "description": "Attachment id (rich-text variant).",
31076
+ "format": "int64"
31077
+ },
31078
+ "sgid": {
31079
+ "type": "string",
31080
+ "description": "Signed global id of the attachment (rich-text variant)."
31081
+ },
31082
+ "previewable": {
31083
+ "type": "boolean",
31084
+ "description": "Whether the blob can be previewed (rich-text variant)."
31085
+ },
31086
+ "preview_url": {
31087
+ "type": "string",
31088
+ "description": "Full-size preview URL (rich-text variant)."
31089
+ },
31090
+ "thumbnail_url": {
31091
+ "type": "string",
31092
+ "description": "Thumbnail URL (rich-text variant)."
31093
+ },
31094
+ "width": {
31095
+ "type": "integer",
31096
+ "description": "Pixel width (rich-text variant) — null for non-image blobs and may be\nfloat-spelled (`1024.0`); see `RichTextAttachment.width`.",
31097
+ "format": "int32",
31098
+ "nullable": true,
31099
+ "x-go-type": "types.FlexInt",
31100
+ "x-go-type-import": {
31101
+ "path": "github.com/basecamp/basecamp-sdk/go/pkg/types"
31102
+ }
31103
+ },
31104
+ "height": {
31105
+ "type": "integer",
31106
+ "description": "See `width` (rich-text variant).",
31107
+ "format": "int32",
31108
+ "nullable": true,
31109
+ "x-go-type": "types.FlexInt",
31110
+ "x-go-type-import": {
31111
+ "path": "github.com/basecamp/basecamp-sdk/go/pkg/types"
31112
+ }
31113
+ },
31114
+ "title": {
31115
+ "type": "string",
31116
+ "description": "Title of the attachment recording (chat upload-line variant)."
31117
+ },
31118
+ "url": {
31119
+ "type": "string",
31120
+ "description": "Browser preview URL of the blob (chat upload-line variant)."
31121
+ }
31122
+ },
31123
+ "required": [
31124
+ "byte_size",
31125
+ "content_type",
31126
+ "download_url",
31127
+ "filename"
30723
31128
  ]
30724
31129
  },
30725
31130
  "SearchType": {
@@ -30787,6 +31192,21 @@
30787
31192
  "SetClientVisibilityResponseContent": {
30788
31193
  "$ref": "#/components/schemas/Recording"
30789
31194
  },
31195
+ "StorageLimitErrorResponseContent": {
31196
+ "type": "object",
31197
+ "description": "The account has reached its file storage limit.\n\nRaised by ResourceLimits#ensure_account_can_upload_files ahead of any operation\nthat stores new bytes. No retry can satisfy it: the account needs more storage,\nso this maps to `limit_exceeded` rather than a retryable server error.",
31198
+ "properties": {
31199
+ "error": {
31200
+ "type": "string"
31201
+ },
31202
+ "message": {
31203
+ "type": "string"
31204
+ }
31205
+ },
31206
+ "required": [
31207
+ "error"
31208
+ ]
31209
+ },
30790
31210
  "SubscribeResponseContent": {
30791
31211
  "$ref": "#/components/schemas/Subscription"
30792
31212
  },
@@ -31714,6 +32134,9 @@
31714
32134
  "status": {
31715
32135
  "type": "string"
31716
32136
  },
32137
+ "visible_to_clients": {
32138
+ "type": "boolean"
32139
+ },
31717
32140
  "created_at": {
31718
32141
  "type": "string",
31719
32142
  "x-go-type": "time.Time",
@@ -31731,15 +32154,12 @@
31731
32154
  "title": {
31732
32155
  "type": "string"
31733
32156
  },
31734
- "name": {
31735
- "type": "string"
31736
- },
31737
- "enabled": {
32157
+ "inherits_status": {
31738
32158
  "type": "boolean"
31739
32159
  },
31740
- "position": {
31741
- "type": "integer",
31742
- "format": "int32"
32160
+ "type": {
32161
+ "type": "string",
32162
+ "description": "The tool's recordable type, e.g. `Chat::Transcript`, `Todoset`, `Vault`."
31743
32163
  },
31744
32164
  "url": {
31745
32165
  "type": "string"
@@ -31747,17 +32167,45 @@
31747
32167
  "app_url": {
31748
32168
  "type": "string"
31749
32169
  },
32170
+ "bookmark_url": {
32171
+ "type": "string"
32172
+ },
32173
+ "subscription_url": {
32174
+ "type": "string",
32175
+ "description": "Absent for tool types that are not subscribable."
32176
+ },
32177
+ "position": {
32178
+ "type": "integer",
32179
+ "description": "Emitted only for a positioned recording. For a docked tool that makes an\nabsent position the disabled signal — disabling removes the tool from the\ndock without deleting it. Positioning is independent of dockedness, so\nthis does not generalize: a nested vault is not docked and is positioned.",
32180
+ "format": "int32"
32181
+ },
32182
+ "parent": {
32183
+ "$ref": "#/components/schemas/RecordingParent"
32184
+ },
31750
32185
  "bucket": {
31751
32186
  "$ref": "#/components/schemas/RecordingBucket"
32187
+ },
32188
+ "creator": {
32189
+ "$ref": "#/components/schemas/Person"
32190
+ },
32191
+ "name": {
32192
+ "type": "string",
32193
+ "description": "Not emitted by this projection. The dock array on a project\n(`DockItem$name`) carries the tool's slug; this key is absent from every\nGetTool/CreateTool/UpdateTool response."
32194
+ },
32195
+ "enabled": {
32196
+ "type": "boolean",
32197
+ "description": "Not emitted by this projection. The dock array on a project\n(`DockItem$enabled`) is the authoritative enabled flag; on a docked tool's\nown response, an absent `position` is the equivalent signal."
31752
32198
  }
31753
32199
  },
31754
32200
  "required": [
31755
32201
  "created_at",
31756
- "enabled",
32202
+ "creator",
31757
32203
  "id",
31758
- "name",
32204
+ "inherits_status",
31759
32205
  "title",
31760
- "updated_at"
32206
+ "type",
32207
+ "updated_at",
32208
+ "visible_to_clients"
31761
32209
  ]
31762
32210
  },
31763
32211
  "UnauthorizedErrorResponseContent": {
@@ -32793,6 +33241,87 @@
32793
33241
  "visible_to_clients"
32794
33242
  ]
32795
33243
  },
33244
+ "UploadVersion": {
33245
+ "type": "object",
33246
+ "description": "A version event for an upload, from GET /uploads/{id}/versions.json.\n\n`action` is one of `created`, `active` (the upload's publication) or `blob_changed`\n(a file replacement). To list the file's PAST versions, select entries that carry\nan `upload` whose `current` is false — the original file arrives as `created` or\n`active`, never `blob_changed`, so filtering on that action drops the original\nand keeps the current file instead. This is an Event plus the file it recorded, rendered by its own\npartial rather than the shared event one, so upload fields don't leak onto todo,\nmessage and card events.",
33247
+ "properties": {
33248
+ "id": {
33249
+ "type": "integer",
33250
+ "format": "int64"
33251
+ },
33252
+ "recording_id": {
33253
+ "type": "integer",
33254
+ "format": "int64"
33255
+ },
33256
+ "action": {
33257
+ "type": "string"
33258
+ },
33259
+ "details": {
33260
+ "$ref": "#/components/schemas/EventDetails"
33261
+ },
33262
+ "created_at": {
33263
+ "type": "string",
33264
+ "x-go-type": "time.Time",
33265
+ "x-go-type-import": {
33266
+ "path": "time"
33267
+ }
33268
+ },
33269
+ "creator": {
33270
+ "$ref": "#/components/schemas/Person"
33271
+ },
33272
+ "boosts_count": {
33273
+ "type": "integer",
33274
+ "format": "int32"
33275
+ },
33276
+ "boosts_url": {
33277
+ "type": "string"
33278
+ },
33279
+ "upload": {
33280
+ "$ref": "#/components/schemas/UploadVersionFile"
33281
+ }
33282
+ },
33283
+ "required": [
33284
+ "action",
33285
+ "created_at",
33286
+ "creator",
33287
+ "id",
33288
+ "recording_id"
33289
+ ]
33290
+ },
33291
+ "UploadVersionFile": {
33292
+ "type": "object",
33293
+ "description": "The file a version event recorded — a reduced projection, not an Upload.",
33294
+ "properties": {
33295
+ "content_type": {
33296
+ "type": "string"
33297
+ },
33298
+ "byte_size": {
33299
+ "type": "integer",
33300
+ "format": "int64"
33301
+ },
33302
+ "filename": {
33303
+ "type": "string"
33304
+ },
33305
+ "download_url": {
33306
+ "type": "string",
33307
+ "description": "Fetches THIS version's bytes. The upload's own download_url always serves the\nlatest, which is the whole point of the feature.",
33308
+ "x-basecamp-auth-routable-url": {}
33309
+ },
33310
+ "app_download_url": {
33311
+ "type": "string"
33312
+ },
33313
+ "current": {
33314
+ "type": "boolean",
33315
+ "description": "True for the newest version *event*, and for exactly one element of any\nnon-empty response. The renderer computes it positionally — `event ==\n@events.first` over a reverse-chronological list — so it is a property of\nordering, not of what the upload currently points at, and it cannot be\nzero or plural.\n\nThat distinction is the whole caveat: `current` does NOT mean \"this is the\nfile the upload's own download_url serves\". A metadata-only PUT swaps in a\nrecordable carrying the same blob and emits no event, so afterwards no\nevent references the upload's current recordable — and this flag still\nmarks exactly one element, the newest event. bc3 pins that case by name in\n\"exactly one version is current after a metadata-only update\"."
33316
+ }
33317
+ },
33318
+ "required": [
33319
+ "app_download_url",
33320
+ "current",
33321
+ "download_url",
33322
+ "filename"
33323
+ ]
33324
+ },
32796
33325
  "ValidationErrorResponseContent": {
32797
33326
  "type": "object",
32798
33327
  "properties": {