@37signals/basecamp 0.11.0 → 0.13.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 (304) hide show
  1. package/README.md +112 -16
  2. package/dist/.build-complete +0 -0
  3. package/dist/client.d.ts +65 -11
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +235 -215
  6. package/dist/client.js.map +1 -1
  7. package/dist/download.d.ts +7 -0
  8. package/dist/download.d.ts.map +1 -1
  9. package/dist/download.js +82 -22
  10. package/dist/download.js.map +1 -1
  11. package/dist/errors.d.ts +19 -1
  12. package/dist/errors.d.ts.map +1 -1
  13. package/dist/errors.js +128 -15
  14. package/dist/errors.js.map +1 -1
  15. package/dist/generated/metadata.d.ts.map +1 -1
  16. package/dist/generated/metadata.js +443 -133
  17. package/dist/generated/metadata.js.map +1 -1
  18. package/dist/generated/metadata.ts +443 -133
  19. package/dist/generated/openapi-stripped.json +8999 -4907
  20. package/dist/generated/path-mapping.d.ts.map +1 -1
  21. package/dist/generated/path-mapping.js +40 -16
  22. package/dist/generated/path-mapping.js.map +1 -1
  23. package/dist/generated/path-mapping.ts +40 -16
  24. package/dist/generated/schema.d.ts +5508 -2346
  25. package/dist/generated/services/bookmarks.d.ts +76 -0
  26. package/dist/generated/services/bookmarks.d.ts.map +1 -0
  27. package/dist/generated/services/bookmarks.js +114 -0
  28. package/dist/generated/services/bookmarks.js.map +1 -0
  29. package/dist/generated/services/bookmarks.ts +158 -0
  30. package/dist/generated/services/boosts.d.ts +10 -0
  31. package/dist/generated/services/boosts.d.ts.map +1 -1
  32. package/dist/generated/services/boosts.js +8 -0
  33. package/dist/generated/services/boosts.js.map +1 -1
  34. package/dist/generated/services/boosts.ts +12 -0
  35. package/dist/generated/services/calendars.d.ts +47 -0
  36. package/dist/generated/services/calendars.d.ts.map +1 -0
  37. package/dist/generated/services/calendars.js +73 -0
  38. package/dist/generated/services/calendars.js.map +1 -0
  39. package/dist/generated/services/calendars.ts +102 -0
  40. package/dist/generated/services/campfires.d.ts +54 -40
  41. package/dist/generated/services/campfires.d.ts.map +1 -1
  42. package/dist/generated/services/campfires.js +82 -65
  43. package/dist/generated/services/campfires.js.map +1 -1
  44. package/dist/generated/services/campfires.ts +107 -85
  45. package/dist/generated/services/cards.d.ts +5 -0
  46. package/dist/generated/services/cards.d.ts.map +1 -1
  47. package/dist/generated/services/cards.js +4 -0
  48. package/dist/generated/services/cards.js.map +1 -1
  49. package/dist/generated/services/cards.ts +6 -0
  50. package/dist/generated/services/checkins.d.ts +14 -0
  51. package/dist/generated/services/checkins.d.ts.map +1 -1
  52. package/dist/generated/services/checkins.js +14 -1
  53. package/dist/generated/services/checkins.js.map +1 -1
  54. package/dist/generated/services/checkins.ts +20 -0
  55. package/dist/generated/services/client-approvals.d.ts +6 -3
  56. package/dist/generated/services/client-approvals.d.ts.map +1 -1
  57. package/dist/generated/services/client-approvals.js +8 -5
  58. package/dist/generated/services/client-approvals.js.map +1 -1
  59. package/dist/generated/services/client-approvals.ts +10 -5
  60. package/dist/generated/services/client-correspondences.d.ts +6 -3
  61. package/dist/generated/services/client-correspondences.d.ts.map +1 -1
  62. package/dist/generated/services/client-correspondences.js +8 -5
  63. package/dist/generated/services/client-correspondences.js.map +1 -1
  64. package/dist/generated/services/client-correspondences.ts +10 -5
  65. package/dist/generated/services/client-replies.d.ts +11 -4
  66. package/dist/generated/services/client-replies.d.ts.map +1 -1
  67. package/dist/generated/services/client-replies.js +16 -8
  68. package/dist/generated/services/client-replies.js.map +1 -1
  69. package/dist/generated/services/client-replies.ts +18 -8
  70. package/dist/generated/services/cloud-files.d.ts +92 -0
  71. package/dist/generated/services/cloud-files.d.ts.map +1 -0
  72. package/dist/generated/services/cloud-files.js +121 -0
  73. package/dist/generated/services/cloud-files.js.map +1 -0
  74. package/dist/generated/services/cloud-files.ts +188 -0
  75. package/dist/generated/services/comments.d.ts +5 -0
  76. package/dist/generated/services/comments.d.ts.map +1 -1
  77. package/dist/generated/services/comments.js +4 -0
  78. package/dist/generated/services/comments.js.map +1 -1
  79. package/dist/generated/services/comments.ts +6 -0
  80. package/dist/generated/services/documents.d.ts +12 -7
  81. package/dist/generated/services/documents.d.ts.map +1 -1
  82. package/dist/generated/services/documents.js +10 -6
  83. package/dist/generated/services/documents.js.map +1 -1
  84. package/dist/generated/services/documents.ts +14 -8
  85. package/dist/generated/services/drafts.d.ts +38 -0
  86. package/dist/generated/services/drafts.d.ts.map +1 -0
  87. package/dist/generated/services/drafts.js +40 -0
  88. package/dist/generated/services/drafts.js.map +1 -0
  89. package/dist/generated/services/drafts.ts +67 -0
  90. package/dist/generated/services/events.d.ts +5 -0
  91. package/dist/generated/services/events.d.ts.map +1 -1
  92. package/dist/generated/services/events.js +4 -0
  93. package/dist/generated/services/events.js.map +1 -1
  94. package/dist/generated/services/events.ts +6 -0
  95. package/dist/generated/services/everything.d.ts +83 -16
  96. package/dist/generated/services/everything.d.ts.map +1 -1
  97. package/dist/generated/services/everything.js +23 -13
  98. package/dist/generated/services/everything.js.map +1 -1
  99. package/dist/generated/services/everything.ts +100 -25
  100. package/dist/generated/services/folders.d.ts +96 -0
  101. package/dist/generated/services/folders.d.ts.map +1 -0
  102. package/dist/generated/services/folders.js +140 -0
  103. package/dist/generated/services/folders.js.map +1 -0
  104. package/dist/generated/services/folders.ts +201 -0
  105. package/dist/generated/services/forwards.d.ts +7 -20
  106. package/dist/generated/services/forwards.d.ts.map +1 -1
  107. package/dist/generated/services/forwards.js +6 -35
  108. package/dist/generated/services/forwards.js.map +1 -1
  109. package/dist/generated/services/forwards.ts +10 -48
  110. package/dist/generated/services/gauges.d.ts +7 -0
  111. package/dist/generated/services/gauges.d.ts.map +1 -1
  112. package/dist/generated/services/gauges.js +5 -1
  113. package/dist/generated/services/gauges.js.map +1 -1
  114. package/dist/generated/services/gauges.ts +9 -1
  115. package/dist/generated/services/google-documents.d.ts +98 -0
  116. package/dist/generated/services/google-documents.d.ts.map +1 -0
  117. package/dist/generated/services/google-documents.js +123 -0
  118. package/dist/generated/services/google-documents.js.map +1 -0
  119. package/dist/generated/services/google-documents.ts +196 -0
  120. package/dist/generated/services/index.d.ts +12 -5
  121. package/dist/generated/services/index.d.ts.map +1 -1
  122. package/dist/generated/services/index.js +12 -5
  123. package/dist/generated/services/index.js.map +1 -1
  124. package/dist/generated/services/index.ts +12 -5
  125. package/dist/generated/services/messages.d.ts +2 -0
  126. package/dist/generated/services/messages.d.ts.map +1 -1
  127. package/dist/generated/services/messages.js +1 -1
  128. package/dist/generated/services/messages.js.map +1 -1
  129. package/dist/generated/services/messages.ts +3 -1
  130. package/dist/generated/services/my-assignments.d.ts +52 -0
  131. package/dist/generated/services/my-assignments.d.ts.map +1 -1
  132. package/dist/generated/services/my-assignments.js +71 -0
  133. package/dist/generated/services/my-assignments.js.map +1 -1
  134. package/dist/generated/services/my-assignments.ts +104 -0
  135. package/dist/generated/services/my-notes.d.ts +45 -0
  136. package/dist/generated/services/my-notes.d.ts.map +1 -0
  137. package/dist/generated/services/my-notes.js +62 -0
  138. package/dist/generated/services/my-notes.js.map +1 -0
  139. package/dist/generated/services/my-notes.ts +92 -0
  140. package/dist/generated/services/my-notifications.d.ts +4 -2
  141. package/dist/generated/services/my-notifications.d.ts.map +1 -1
  142. package/dist/generated/services/my-notifications.js.map +1 -1
  143. package/dist/generated/services/my-notifications.ts +4 -2
  144. package/dist/generated/services/people.d.ts +11 -1
  145. package/dist/generated/services/people.d.ts.map +1 -1
  146. package/dist/generated/services/people.js +13 -2
  147. package/dist/generated/services/people.js.map +1 -1
  148. package/dist/generated/services/people.ts +15 -1
  149. package/dist/generated/services/projects.d.ts +26 -0
  150. package/dist/generated/services/projects.d.ts.map +1 -1
  151. package/dist/generated/services/projects.js +49 -1
  152. package/dist/generated/services/projects.js.map +1 -1
  153. package/dist/generated/services/projects.ts +61 -1
  154. package/dist/generated/services/recordings.d.ts +2 -12
  155. package/dist/generated/services/recordings.d.ts.map +1 -1
  156. package/dist/generated/services/recordings.js +1 -26
  157. package/dist/generated/services/recordings.js.map +1 -1
  158. package/dist/generated/services/recordings.ts +3 -31
  159. package/dist/generated/services/reports.d.ts +8 -12
  160. package/dist/generated/services/reports.d.ts.map +1 -1
  161. package/dist/generated/services/reports.js +11 -5
  162. package/dist/generated/services/reports.js.map +1 -1
  163. package/dist/generated/services/reports.ts +13 -14
  164. package/dist/generated/services/schedules.d.ts +94 -15
  165. package/dist/generated/services/schedules.d.ts.map +1 -1
  166. package/dist/generated/services/schedules.js +19 -8
  167. package/dist/generated/services/schedules.js.map +1 -1
  168. package/dist/generated/services/schedules.ts +107 -17
  169. package/dist/generated/services/search.d.ts +2 -0
  170. package/dist/generated/services/search.d.ts.map +1 -1
  171. package/dist/generated/services/search.js +1 -1
  172. package/dist/generated/services/search.js.map +1 -1
  173. package/dist/generated/services/search.ts +3 -1
  174. package/dist/generated/services/templates.d.ts +2 -0
  175. package/dist/generated/services/templates.d.ts.map +1 -1
  176. package/dist/generated/services/templates.js +1 -1
  177. package/dist/generated/services/templates.js.map +1 -1
  178. package/dist/generated/services/templates.ts +3 -1
  179. package/dist/generated/services/timeline.d.ts +2 -0
  180. package/dist/generated/services/timeline.d.ts.map +1 -1
  181. package/dist/generated/services/timeline.js +1 -0
  182. package/dist/generated/services/timeline.js.map +1 -1
  183. package/dist/generated/services/timeline.ts +3 -0
  184. package/dist/generated/services/timesheets.d.ts +16 -0
  185. package/dist/generated/services/timesheets.d.ts.map +1 -1
  186. package/dist/generated/services/timesheets.js +26 -2
  187. package/dist/generated/services/timesheets.js.map +1 -1
  188. package/dist/generated/services/timesheets.ts +35 -2
  189. package/dist/generated/services/todolist-groups.d.ts +11 -6
  190. package/dist/generated/services/todolist-groups.d.ts.map +1 -1
  191. package/dist/generated/services/todolist-groups.js +7 -3
  192. package/dist/generated/services/todolist-groups.js.map +1 -1
  193. package/dist/generated/services/todolist-groups.ts +13 -7
  194. package/dist/generated/services/todolists.d.ts +15 -13
  195. package/dist/generated/services/todolists.d.ts.map +1 -1
  196. package/dist/generated/services/todolists.js +11 -8
  197. package/dist/generated/services/todolists.js.map +1 -1
  198. package/dist/generated/services/todolists.ts +19 -14
  199. package/dist/generated/services/todos.d.ts +35 -12
  200. package/dist/generated/services/todos.d.ts.map +1 -1
  201. package/dist/generated/services/todos.js +47 -25
  202. package/dist/generated/services/todos.js.map +1 -1
  203. package/dist/generated/services/todos.ts +74 -30
  204. package/dist/generated/services/uploads.d.ts +5 -0
  205. package/dist/generated/services/uploads.d.ts.map +1 -1
  206. package/dist/generated/services/uploads.js +4 -0
  207. package/dist/generated/services/uploads.js.map +1 -1
  208. package/dist/generated/services/uploads.ts +6 -0
  209. package/dist/generated/services/vaults.d.ts +5 -0
  210. package/dist/generated/services/vaults.d.ts.map +1 -1
  211. package/dist/generated/services/vaults.js +4 -0
  212. package/dist/generated/services/vaults.js.map +1 -1
  213. package/dist/generated/services/vaults.ts +6 -0
  214. package/dist/hooks/otel.d.ts +1 -1
  215. package/dist/hooks/otel.js +1 -1
  216. package/dist/index.d.ts +21 -11
  217. package/dist/index.d.ts.map +1 -1
  218. package/dist/index.js +24 -9
  219. package/dist/index.js.map +1 -1
  220. package/dist/oauth/discovery.d.ts.map +1 -1
  221. package/dist/oauth/discovery.js +1 -0
  222. package/dist/oauth/discovery.js.map +1 -1
  223. package/dist/pagination-utils.d.ts +46 -0
  224. package/dist/pagination-utils.d.ts.map +1 -1
  225. package/dist/pagination-utils.js +85 -2
  226. package/dist/pagination-utils.js.map +1 -1
  227. package/dist/pagination.d.ts +12 -1
  228. package/dist/pagination.d.ts.map +1 -1
  229. package/dist/pagination.js +1 -1
  230. package/dist/pagination.js.map +1 -1
  231. package/dist/retry.d.ts +110 -0
  232. package/dist/retry.d.ts.map +1 -0
  233. package/dist/retry.js +253 -0
  234. package/dist/retry.js.map +1 -0
  235. package/dist/services/base.d.ts.map +1 -1
  236. package/dist/services/base.js +59 -5
  237. package/dist/services/base.js.map +1 -1
  238. package/dist/services/cards-extensions.d.ts +26 -21
  239. package/dist/services/cards-extensions.d.ts.map +1 -1
  240. package/dist/services/cards-extensions.js +28 -31
  241. package/dist/services/cards-extensions.js.map +1 -1
  242. package/dist/services/documents-extensions.d.ts +122 -0
  243. package/dist/services/documents-extensions.d.ts.map +1 -0
  244. package/dist/services/documents-extensions.js +125 -0
  245. package/dist/services/documents-extensions.js.map +1 -0
  246. package/dist/services/merge-safe.d.ts +167 -0
  247. package/dist/services/merge-safe.d.ts.map +1 -0
  248. package/dist/services/merge-safe.js +217 -0
  249. package/dist/services/merge-safe.js.map +1 -0
  250. package/dist/services/schedules-extensions.d.ts +266 -0
  251. package/dist/services/schedules-extensions.d.ts.map +1 -0
  252. package/dist/services/schedules-extensions.js +268 -0
  253. package/dist/services/schedules-extensions.js.map +1 -0
  254. package/dist/services/todolists-extensions.d.ts +110 -0
  255. package/dist/services/todolists-extensions.d.ts.map +1 -0
  256. package/dist/services/todolists-extensions.js +262 -0
  257. package/dist/services/todolists-extensions.js.map +1 -0
  258. package/dist/services/todos-extensions.d.ts +12 -1
  259. package/dist/services/todos-extensions.d.ts.map +1 -1
  260. package/dist/services/todos-extensions.js +27 -8
  261. package/dist/services/todos-extensions.js.map +1 -1
  262. package/package.json +5 -4
  263. package/src/generated/metadata.ts +443 -133
  264. package/src/generated/openapi-stripped.json +8999 -4907
  265. package/src/generated/path-mapping.ts +40 -16
  266. package/src/generated/schema.d.ts +5508 -2346
  267. package/src/generated/services/bookmarks.ts +158 -0
  268. package/src/generated/services/boosts.ts +12 -0
  269. package/src/generated/services/calendars.ts +102 -0
  270. package/src/generated/services/campfires.ts +107 -85
  271. package/src/generated/services/cards.ts +6 -0
  272. package/src/generated/services/checkins.ts +20 -0
  273. package/src/generated/services/client-approvals.ts +10 -5
  274. package/src/generated/services/client-correspondences.ts +10 -5
  275. package/src/generated/services/client-replies.ts +18 -8
  276. package/src/generated/services/cloud-files.ts +188 -0
  277. package/src/generated/services/comments.ts +6 -0
  278. package/src/generated/services/documents.ts +14 -8
  279. package/src/generated/services/drafts.ts +67 -0
  280. package/src/generated/services/events.ts +6 -0
  281. package/src/generated/services/everything.ts +100 -25
  282. package/src/generated/services/folders.ts +201 -0
  283. package/src/generated/services/forwards.ts +10 -48
  284. package/src/generated/services/gauges.ts +9 -1
  285. package/src/generated/services/google-documents.ts +196 -0
  286. package/src/generated/services/index.ts +12 -5
  287. package/src/generated/services/messages.ts +3 -1
  288. package/src/generated/services/my-assignments.ts +104 -0
  289. package/src/generated/services/my-notes.ts +92 -0
  290. package/src/generated/services/my-notifications.ts +4 -2
  291. package/src/generated/services/people.ts +15 -1
  292. package/src/generated/services/projects.ts +61 -1
  293. package/src/generated/services/recordings.ts +3 -31
  294. package/src/generated/services/reports.ts +13 -14
  295. package/src/generated/services/schedules.ts +107 -17
  296. package/src/generated/services/search.ts +3 -1
  297. package/src/generated/services/templates.ts +3 -1
  298. package/src/generated/services/timeline.ts +3 -0
  299. package/src/generated/services/timesheets.ts +35 -2
  300. package/src/generated/services/todolist-groups.ts +13 -7
  301. package/src/generated/services/todolists.ts +19 -14
  302. package/src/generated/services/todos.ts +74 -30
  303. package/src/generated/services/uploads.ts +6 -0
  304. package/src/generated/services/vaults.ts +6 -0
@@ -22,16 +22,8 @@ export type Person = components["schemas"]["Person"];
22
22
  * Options for progress.
23
23
  */
24
24
  export interface ProgressReportOptions extends PaginationOptions {
25
- }
26
-
27
- /**
28
- * Options for upcoming.
29
- */
30
- export interface UpcomingReportOptions {
31
- /** Window starts on */
32
- windowStartsOn?: string;
33
- /** Window ends on */
34
- windowEndsOn?: string;
25
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
26
+ page?: number;
35
27
  }
36
28
 
37
29
  /**
@@ -46,6 +38,8 @@ export interface AssignedReportOptions {
46
38
  * Options for personProgress.
47
39
  */
48
40
  export interface PersonProgressReportOptions extends PaginationOptions {
41
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
42
+ page?: number;
49
43
  }
50
44
 
51
45
 
@@ -78,6 +72,9 @@ export class ReportsService extends BaseService {
78
72
  },
79
73
  () =>
80
74
  this.client.GET("/reports/progress.json", {
75
+ params: {
76
+ query: { page: options?.page },
77
+ },
81
78
  })
82
79
  , options
83
80
  );
@@ -85,15 +82,16 @@ export class ReportsService extends BaseService {
85
82
 
86
83
  /**
87
84
  * Get upcoming schedule entries and assignable items within a date window.
88
- * @param options - Optional query parameters
85
+ * @param windowStartsOn - Inclusive first day of the window, `YYYY-MM-DD`. Required — BC3 answers 400 without it.
86
+ * @param windowEndsOn - Inclusive last day of the window, `YYYY-MM-DD`. Required — BC3 answers 400 without it.
89
87
  * @returns The upcoming_schedule
90
88
  *
91
89
  * @example
92
90
  * ```ts
93
- * const result = await client.reports.upcoming();
91
+ * const result = await client.reports.upcoming("window_starts_on", "window_ends_on");
94
92
  * ```
95
93
  */
96
- async upcoming(options?: UpcomingReportOptions): Promise<components["schemas"]["GetUpcomingScheduleResponseContent"]> {
94
+ async upcoming(windowStartsOn: string, windowEndsOn: string): Promise<components["schemas"]["GetUpcomingScheduleResponseContent"]> {
97
95
  const response = await this.request(
98
96
  {
99
97
  service: "Reports",
@@ -104,7 +102,7 @@ export class ReportsService extends BaseService {
104
102
  () =>
105
103
  this.client.GET("/reports/schedules/upcoming.json", {
106
104
  params: {
107
- query: { "window_starts_on": options?.windowStartsOn, "window_ends_on": options?.windowEndsOn },
105
+ query: { "window_starts_on": windowStartsOn, "window_ends_on": windowEndsOn },
108
106
  },
109
107
  })
110
108
  );
@@ -190,6 +188,7 @@ export class ReportsService extends BaseService {
190
188
  this.client.GET("/reports/users/progress/{personId}.json", {
191
189
  params: {
192
190
  path: { personId },
191
+ query: { page: options?.page },
193
192
  },
194
193
  })
195
194
  , "events", options
@@ -20,15 +20,17 @@ export type ScheduleEntry = components["schemas"]["ScheduleEntry"];
20
20
  export type Schedule = components["schemas"]["Schedule"];
21
21
 
22
22
  /**
23
- * Request parameters for updateEntry.
23
+ * Request parameters for replaceEntry.
24
24
  */
25
- export interface UpdateEntryScheduleRequest {
25
+ export interface ReplaceEntryScheduleRequest {
26
26
  /** Summary text */
27
27
  summary?: string;
28
- /** Starts at (RFC3339 (e.g., 2024-12-15T09:00:00Z)) */
29
- startsAt?: string;
30
- /** Ends at (RFC3339 (e.g., 2024-12-15T09:00:00Z)) */
31
- endsAt?: string;
28
+ /** The entry's start, as a bare date ("2026-06-01") for an all-day entry or a
29
+ full timestamp otherwise. Same rule as CreateScheduleEntry: send it
30
+ verbatim, never parsed and re-rendered. */
31
+ startsAt: string;
32
+ /** The entry's end. See starts_at for the date-vs-timestamp rule. */
33
+ endsAt: string;
32
34
  /** Rich text description (HTML) */
33
35
  description?: string;
34
36
  /** Replaces the entry's participants.
@@ -41,10 +43,36 @@ including the shape in BC3's own "Update a schedule entry" doc example —
41
43
  silently removed every participant and notified each one. The controller
42
44
  now guards on the request actually addressing participants. */
43
45
  participantIds?: number[];
44
- /** All day */
46
+ /** Whether the entry occupies whole days rather than a time range.
47
+
48
+ Not carved out, and the carve-out list is what makes that dangerous to
49
+ forget: `schedule_entries.all_day` is NOT NULL with a `false` default, so
50
+ omitting this member on a replace resets it — silently converting an
51
+ all-day entry into a midnight-to-midnight timed one. The SDK's merge-safe
52
+ update and edit resend it from the read-back for exactly this reason.
53
+
54
+ Sending an explicit null is worse than omitting it: the column rejects
55
+ NULL, so BC3 raises rather than falling back to the default. The same is
56
+ true of highlighted. */
45
57
  allDay?: boolean;
46
58
  /** Whether to send notifications to relevant people */
47
59
  notify?: boolean;
60
+ /** The entry's join link — a video-call URL or similar, up to 2500
61
+ characters, validated as a URL when present.
62
+
63
+ Omitting this member preserves the current join link; sending an empty
64
+ string clears it. Read it back as `join_url`, never as `url`: the entry's
65
+ `url` is its own Basecamp API URL, written by a partial that renders
66
+ before this one, so BC3 emits the join link under a non-colliding key.
67
+ Echoing the response's `url` into this member would write the API URL into
68
+ the join link. */
69
+ url?: string;
70
+ /** Whether the entry is highlighted on the schedule.
71
+
72
+ Omitting this member preserves the current highlight; sending false
73
+ removes it. Preserved on omission because until basecamp/bc3#12502 the
74
+ field was writable but never returned, so no caller could resend it. */
75
+ highlighted?: boolean;
48
76
  }
49
77
 
50
78
  /**
@@ -61,6 +89,8 @@ export interface UpdateSettingsScheduleRequest {
61
89
  export interface ListEntriesScheduleOptions extends PaginationOptions {
62
90
  /** Filter by status */
63
91
  status?: "active" | "archived" | "trashed";
92
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
93
+ page?: number;
64
94
  }
65
95
 
66
96
  /**
@@ -69,9 +99,21 @@ export interface ListEntriesScheduleOptions extends PaginationOptions {
69
99
  export interface CreateEntryScheduleRequest {
70
100
  /** Summary text */
71
101
  summary: string;
72
- /** Starts at (RFC3339 (e.g., 2024-12-15T09:00:00Z)) */
102
+ /** The entry's start, as a bare date ("2026-06-01") for an all-day entry or a
103
+ full timestamp ("2026-06-01T09:00:00Z") otherwise — the same two forms the
104
+ response renders, and the same two ReplaceScheduleEntry accepts.
105
+
106
+ Create and replace share one permit list:
107
+ `Schedules::Entries::BaseController#base_schedule_entry_params` is what
108
+ both `new_schedule_entry_params` and `update_schedule_entry_params` call,
109
+ and Schedule::Entry does no format-specific parsing of either bound, so
110
+ whatever one operation takes the other takes too.
111
+
112
+ Treat the value as opaque and send it verbatim. Parsing it into a
113
+ date-time type and re-rendering rewrites an all-day entry's bounds into
114
+ midnight timestamps, which is why every SDK models it as a string. */
73
115
  startsAt: string;
74
- /** Ends at (RFC3339 (e.g., 2024-12-15T09:00:00Z)) */
116
+ /** The entry's end. See starts_at for the date-vs-timestamp rule. */
75
117
  endsAt: string;
76
118
  /** Rich text description (HTML) */
77
119
  description?: string;
@@ -81,6 +123,43 @@ export interface CreateEntryScheduleRequest {
81
123
  allDay?: boolean;
82
124
  /** Whether to send notifications to relevant people */
83
125
  notify?: boolean;
126
+ /** The entry's join link — a video-call URL or similar, up to 2500
127
+ characters, validated as a URL when present. A scheme-less value is
128
+ normalized to `https://`.
129
+
130
+ Spell it `url` on the way in and read it back as `join_url`: the response
131
+ key `url` is the entry's own Basecamp API URL, written by a partial that
132
+ renders before this field, so BC3 emits the join link under a
133
+ non-colliding name. Sending `join_url` instead is silently dropped by
134
+ strong parameters — the create succeeds with no join link.
135
+
136
+ Accepted on create since long before it was documented:
137
+ `Schedules::Entries::BaseController#base_schedule_entry_params` permits it
138
+ and `new_schedule_entry_params` passes it through unchanged for API
139
+ requests. Modeling it only on ReplaceScheduleEntry forced callers into a
140
+ three-request read-modify-write for a field the create already took — and
141
+ create is the notifying write, so participants learned about a video call
142
+ before its link existed. */
143
+ url?: string;
144
+ /** Whether the entry is highlighted on the schedule. Defaults to false.
145
+
146
+ Do not send an explicit null: `schedule_entries.highlighted` is NOT NULL,
147
+ so BC3 raises rather than falling back to the default. Omit it instead —
148
+ every SDK's request compactor already drops unset members. */
149
+ highlighted?: boolean;
150
+ /** Publication state at creation — `active|drafted`, defaulting to `active`
151
+ for an API create.
152
+
153
+ A top-level parameter, not part of the entry's attributes: `status` is a
154
+ Recording column, so `wrap_parameters` leaves it outside the
155
+ `schedule_entry` envelope and `Recording::StatusParam#status_param` reads
156
+ it directly. On create it accepts `drafted`, `active`, `archived` or
157
+ `trashed` and raises `ActionController::BadRequest` — a 400, not a 422 —
158
+ for anything else; the two documented values are the two worth sending.
159
+
160
+ Unlike messages and documents, schedule-entry drafts are not listed by
161
+ GetMyDrafts. */
162
+ status?: string;
84
163
  /** Subscriptions */
85
164
  subscriptions?: number[];
86
165
  /** Visible to clients */
@@ -128,22 +207,28 @@ export class SchedulesService extends BaseService {
128
207
  }
129
208
 
130
209
  /**
131
- * Update an existing schedule entry
210
+ * Replace a schedule entry with a new complete representation.
132
211
  * @param entryId - The entry ID
133
- * @param req - Schedule_entry update parameters
212
+ * @param req - Schedule_entry request parameters
134
213
  * @returns The ScheduleEntry
135
- * @throws {BasecampError} If the resource is not found or fields are invalid
214
+ * @throws {BasecampError} If the request fails
136
215
  *
137
216
  * @example
138
217
  * ```ts
139
- * const result = await client.schedules.updateEntry(123, { });
218
+ * const result = await client.schedules.replaceEntry(123, { startsAt: "example", endsAt: "example" });
140
219
  * ```
141
220
  */
142
- async updateEntry(entryId: number, req: UpdateEntryScheduleRequest): Promise<ScheduleEntry> {
221
+ async replaceEntry(entryId: number, req: ReplaceEntryScheduleRequest): Promise<ScheduleEntry> {
222
+ if (!req.startsAt) {
223
+ throw Errors.validation("Starts at is required");
224
+ }
225
+ if (!req.endsAt) {
226
+ throw Errors.validation("Ends at is required");
227
+ }
143
228
  const response = await this.request(
144
229
  {
145
230
  service: "Schedules",
146
- operation: "UpdateScheduleEntry",
231
+ operation: "ReplaceScheduleEntry",
147
232
  resourceType: "schedule_entry",
148
233
  isMutation: true,
149
234
  resourceId: entryId,
@@ -161,6 +246,8 @@ export class SchedulesService extends BaseService {
161
246
  participant_ids: req.participantIds,
162
247
  all_day: req.allDay,
163
248
  notify: req.notify,
249
+ url: req.url,
250
+ highlighted: req.highlighted,
164
251
  },
165
252
  })
166
253
  );
@@ -289,7 +376,7 @@ export class SchedulesService extends BaseService {
289
376
  this.client.GET("/schedules/{scheduleId}/entries.json", {
290
377
  params: {
291
378
  path: { scheduleId },
292
- query: { status: options?.status },
379
+ query: { status: options?.status, page: options?.page },
293
380
  },
294
381
  })
295
382
  , options
@@ -305,7 +392,7 @@ export class SchedulesService extends BaseService {
305
392
  *
306
393
  * @example
307
394
  * ```ts
308
- * const result = await client.schedules.createEntry(123, { summary: "example", startsAt: "2025-06-01T09:00:00Z", endsAt: "2025-06-01T09:00:00Z" });
395
+ * const result = await client.schedules.createEntry(123, { summary: "example", startsAt: "example", endsAt: "example" });
309
396
  * ```
310
397
  */
311
398
  async createEntry(scheduleId: number, req: CreateEntryScheduleRequest): Promise<ScheduleEntry> {
@@ -339,6 +426,9 @@ export class SchedulesService extends BaseService {
339
426
  participant_ids: req.participantIds,
340
427
  all_day: req.allDay,
341
428
  notify: req.notify,
429
+ url: req.url,
430
+ highlighted: req.highlighted,
431
+ status: req.status,
342
432
  subscriptions: req.subscriptions,
343
433
  visible_to_clients: req.visibleToClients,
344
434
  },
@@ -49,6 +49,8 @@ endpoint's `file_search_types`. */
49
49
  * @deprecated prefer creator_ids[].
50
50
  */
51
51
  creatorId?: number;
52
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
53
+ page?: number;
52
54
  }
53
55
 
54
56
 
@@ -83,7 +85,7 @@ export class SearchService extends BaseService {
83
85
  () =>
84
86
  this.client.GET("/search.json", {
85
87
  params: {
86
- query: { q: q, "type_names[]": options?.typeNames, "bucket_ids[]": options?.bucketIds, "creator_ids[]": options?.creatorIds, "file_type": options?.fileType, "exclude_chat": options?.excludeChat, since: options?.since, sort: options?.sort, type: options?.type, "bucket_id": options?.bucketId, "creator_id": options?.creatorId },
88
+ query: { q: q, "type_names[]": options?.typeNames, "bucket_ids[]": options?.bucketIds, "creator_ids[]": options?.creatorIds, "file_type": options?.fileType, "exclude_chat": options?.excludeChat, since: options?.since, sort: options?.sort, type: options?.type, "bucket_id": options?.bucketId, "creator_id": options?.creatorId, page: options?.page },
87
89
  },
88
90
  })
89
91
  , options
@@ -23,6 +23,8 @@ export type Template = components["schemas"]["Template"];
23
23
  export interface ListTemplateOptions extends PaginationOptions {
24
24
  /** Filter by status */
25
25
  status?: "active" | "archived" | "trashed";
26
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
27
+ page?: number;
26
28
  }
27
29
 
28
30
  /**
@@ -87,7 +89,7 @@ export class TemplatesService extends BaseService {
87
89
  () =>
88
90
  this.client.GET("/templates.json", {
89
91
  params: {
90
- query: { status: options?.status },
92
+ query: { status: options?.status, page: options?.page },
91
93
  },
92
94
  })
93
95
  , options
@@ -20,6 +20,8 @@ export type TimelineEvent = components["schemas"]["TimelineEvent"];
20
20
  * Options for projectTimeline.
21
21
  */
22
22
  export interface ProjectTimelineTimelineOptions extends PaginationOptions {
23
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
24
+ page?: number;
23
25
  }
24
26
 
25
27
 
@@ -56,6 +58,7 @@ export class TimelineService extends BaseService {
56
58
  this.client.GET("/projects/{projectId}/timeline.json", {
57
59
  params: {
58
60
  path: { projectId },
61
+ query: { page: options?.page },
59
62
  },
60
63
  })
61
64
  , options
@@ -27,6 +27,8 @@ export interface ForProjectTimesheetOptions extends PaginationOptions {
27
27
  to?: string;
28
28
  /** Person id */
29
29
  personId?: number;
30
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
31
+ page?: number;
30
32
  }
31
33
 
32
34
  /**
@@ -39,6 +41,8 @@ export interface ForRecordingTimesheetOptions extends PaginationOptions {
39
41
  to?: string;
40
42
  /** Person id */
41
43
  personId?: number;
44
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
45
+ page?: number;
42
46
  }
43
47
 
44
48
  /**
@@ -115,7 +119,7 @@ export class TimesheetsService extends BaseService {
115
119
  this.client.GET("/projects/{projectId}/timesheet.json", {
116
120
  params: {
117
121
  path: { projectId },
118
- query: { from: options?.from, to: options?.to, "person_id": options?.personId },
122
+ query: { from: options?.from, to: options?.to, "person_id": options?.personId, page: options?.page },
119
123
  },
120
124
  })
121
125
  , options
@@ -146,7 +150,7 @@ export class TimesheetsService extends BaseService {
146
150
  this.client.GET("/recordings/{recordingId}/timesheet.json", {
147
151
  params: {
148
152
  path: { recordingId },
149
- query: { from: options?.from, to: options?.to, "person_id": options?.personId },
153
+ query: { from: options?.from, to: options?.to, "person_id": options?.personId, page: options?.page },
150
154
  },
151
155
  })
152
156
  , options
@@ -290,4 +294,33 @@ export class TimesheetsService extends BaseService {
290
294
  );
291
295
  return response;
292
296
  }
297
+
298
+ /**
299
+ * Permanently delete a timesheet entry; answers 403 when the caller may not archive or trash it.
300
+ * @param entryId - The entry ID
301
+ * @returns void
302
+ * @throws {BasecampError} If the request fails
303
+ *
304
+ * @example
305
+ * ```ts
306
+ * await client.timesheets.destroy(123);
307
+ * ```
308
+ */
309
+ async destroy(entryId: number): Promise<void> {
310
+ await this.request(
311
+ {
312
+ service: "Timesheets",
313
+ operation: "DestroyTimesheetEntry",
314
+ resourceType: "timesheet_entry",
315
+ isMutation: true,
316
+ resourceId: entryId,
317
+ },
318
+ () =>
319
+ this.client.DELETE("/timesheet_entries/{entryId}", {
320
+ params: {
321
+ path: { entryId },
322
+ },
323
+ })
324
+ );
325
+ }
293
326
  }
@@ -14,8 +14,8 @@ import { Errors } from "../../errors.js";
14
14
  // Types
15
15
  // =============================================================================
16
16
 
17
- /** TodolistGroup entity from the Basecamp API. */
18
- export type TodolistGroup = components["schemas"]["TodolistGroup"];
17
+ /** Todolist entity from the Basecamp API. */
18
+ export type Todolist = components["schemas"]["Todolist"];
19
19
 
20
20
  /**
21
21
  * Request parameters for reposition.
@@ -29,6 +29,8 @@ export interface RepositionTodolistGroupRequest {
29
29
  * Options for list.
30
30
  */
31
31
  export interface ListTodolistGroupOptions extends PaginationOptions {
32
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
33
+ page?: number;
32
34
  }
33
35
 
34
36
  /**
@@ -71,7 +73,7 @@ export class TodolistGroupsService extends BaseService {
71
73
  resourceId: groupId,
72
74
  },
73
75
  () =>
74
- this.client.PUT("/todolists/{groupId}/position.json", {
76
+ this.client.PUT("/todolists/groups/{groupId}/position.json", {
75
77
  params: {
76
78
  path: { groupId },
77
79
  },
@@ -86,14 +88,17 @@ export class TodolistGroupsService extends BaseService {
86
88
  * List groups in a todolist
87
89
  * @param todolistId - The todolist ID
88
90
  * @param options - Optional query parameters
89
- * @returns All TodolistGroup across all pages, with .meta.totalCount
91
+ * @returns All Todolist across all pages, with .meta.totalCount
90
92
  *
91
93
  * @example
92
94
  * ```ts
93
95
  * const result = await client.todolistGroups.list(123);
96
+ *
97
+ * // With options
98
+ * const filtered = await client.todolistGroups.list(123, { page: 1 });
94
99
  * ```
95
100
  */
96
- async list(todolistId: number, options?: ListTodolistGroupOptions): Promise<ListResult<TodolistGroup>> {
101
+ async list(todolistId: number, options?: ListTodolistGroupOptions): Promise<ListResult<Todolist>> {
97
102
  return this.requestPaginated(
98
103
  {
99
104
  service: "TodolistGroups",
@@ -106,6 +111,7 @@ export class TodolistGroupsService extends BaseService {
106
111
  this.client.GET("/todolists/{todolistId}/groups.json", {
107
112
  params: {
108
113
  path: { todolistId },
114
+ query: { page: options?.page },
109
115
  },
110
116
  })
111
117
  , options
@@ -116,7 +122,7 @@ export class TodolistGroupsService extends BaseService {
116
122
  * Create a new group in a todolist
117
123
  * @param todolistId - The todolist ID
118
124
  * @param req - Todolist_group creation parameters
119
- * @returns The TodolistGroup
125
+ * @returns The Todolist
120
126
  * @throws {BasecampError} If required fields are missing or invalid
121
127
  *
122
128
  * @example
@@ -124,7 +130,7 @@ export class TodolistGroupsService extends BaseService {
124
130
  * const result = await client.todolistGroups.create(123, { name: "My example" });
125
131
  * ```
126
132
  */
127
- async create(todolistId: number, req: CreateTodolistGroupRequest): Promise<TodolistGroup> {
133
+ async create(todolistId: number, req: CreateTodolistGroupRequest): Promise<Todolist> {
128
134
  if (!req.name) {
129
135
  throw Errors.validation("Name is required");
130
136
  }
@@ -18,12 +18,12 @@ import { Errors } from "../../errors.js";
18
18
  export type Todolist = components["schemas"]["Todolist"];
19
19
 
20
20
  /**
21
- * Request parameters for update.
21
+ * Request parameters for replace.
22
22
  */
23
- export interface UpdateTodolistRequest {
24
- /** Name (required for both Todolist and TodolistGroup) */
25
- name?: string;
26
- /** Description (Todolist only, ignored for groups) */
23
+ export interface ReplaceTodolistRequest {
24
+ /** Name (required for a to-do list and for a group alike) - presence-validated server-side, so omitting it is a 422, not a preserve */
25
+ name: string;
26
+ /** Description (rich text HTML) - writable for a todolist group as well as a todolist, and omitting it clears it either way */
27
27
  description?: string;
28
28
  }
29
29
 
@@ -41,6 +41,8 @@ export interface RepositionTodolistRequest {
41
41
  export interface ListTodolistOptions extends PaginationOptions {
42
42
  /** Filter by status */
43
43
  status?: "active" | "archived" | "trashed";
44
+ /** Page number for paginating through results. Defaults to 1. A positive value selects exactly that page, not a starting offset; see SPEC section 8. */
45
+ page?: number;
44
46
  }
45
47
 
46
48
  /**
@@ -68,7 +70,7 @@ export class TodolistsService extends BaseService {
68
70
  /**
69
71
  * Get a single todolist or todolist group by id
70
72
  * @param id - The id
71
- * @returns The todolist_or_group
73
+ * @returns The Todolist
72
74
  * @throws {BasecampError} If the resource is not found
73
75
  *
74
76
  * @example
@@ -76,7 +78,7 @@ export class TodolistsService extends BaseService {
76
78
  * const result = await client.todolists.get(123);
77
79
  * ```
78
80
  */
79
- async get(id: number): Promise<components["schemas"]["GetTodolistOrGroupResponseContent"]> {
81
+ async get(id: number): Promise<Todolist> {
80
82
  const response = await this.request(
81
83
  {
82
84
  service: "Todolists",
@@ -96,18 +98,21 @@ export class TodolistsService extends BaseService {
96
98
  }
97
99
 
98
100
  /**
99
- * Update an existing todolist or todolist group
101
+ * Replace a todolist (or todolist group) with a new complete representation.
100
102
  * @param id - The id
101
- * @param req - Todolist_or_group update parameters
102
- * @returns The todolist_or_group
103
- * @throws {BasecampError} If the resource is not found or fields are invalid
103
+ * @param req - Todolist_or_group request parameters
104
+ * @returns The Todolist
105
+ * @throws {BasecampError} If the request fails
104
106
  *
105
107
  * @example
106
108
  * ```ts
107
- * const result = await client.todolists.update(123, { });
109
+ * const result = await client.todolists.replace(123, { name: "My example" });
108
110
  * ```
109
111
  */
110
- async update(id: number, req: UpdateTodolistRequest): Promise<components["schemas"]["UpdateTodolistOrGroupResponseContent"]> {
112
+ async replace(id: number, req: ReplaceTodolistRequest): Promise<Todolist> {
113
+ if (!req.name) {
114
+ throw Errors.validation("Name is required");
115
+ }
111
116
  const response = await this.request(
112
117
  {
113
118
  service: "Todolists",
@@ -190,7 +195,7 @@ export class TodolistsService extends BaseService {
190
195
  this.client.GET("/todosets/{todosetId}/todolists.json", {
191
196
  params: {
192
197
  path: { todosetId },
193
- query: { status: options?.status },
198
+ query: { status: options?.status, page: options?.page },
194
199
  },
195
200
  })
196
201
  , options