basecamp-client 1.0.1

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.
package/dist/index.mjs ADDED
@@ -0,0 +1,3180 @@
1
+ // src/buildClient.ts
2
+ import { initClient as tsRestInitClient } from "@ts-rest/core";
3
+
4
+ // src/contract/index.ts
5
+ import { z as z59 } from "zod";
6
+
7
+ // src/contract/c.ts
8
+ import { initContract } from "@ts-rest/core";
9
+ var c = initContract();
10
+
11
+ // src/contract/resources/communications/message-boards.ts
12
+ import { z as z3 } from "zod";
13
+
14
+ // src/contract/schemas/common.ts
15
+ import { z } from "zod";
16
+ var BasecampIdSchema = z.number().int().nonnegative();
17
+ var BasecampIdParamSchema = z.coerce.number().int().nonnegative();
18
+ var IsoDateTimeSchema = z.string().datetime({ offset: true });
19
+ var IsoDateSchema = z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be formatted as YYYY-MM-DD");
20
+ var RecordingStatusSchema = z.enum(["active", "trashed"]).or(z.string());
21
+ var HtmlStringSchema = z.string().min(0);
22
+ var BucketRefSchema = z.object({
23
+ id: BasecampIdSchema,
24
+ name: z.string(),
25
+ type: z.string()
26
+ });
27
+ var RecordingRefSchema = z.object({
28
+ id: BasecampIdSchema,
29
+ title: z.string(),
30
+ type: z.string(),
31
+ url: z.string().url(),
32
+ app_url: z.string().url()
33
+ });
34
+ var PersonSummarySchema = z.object({
35
+ id: BasecampIdSchema,
36
+ attachable_sgid: z.string().min(1),
37
+ name: z.string(),
38
+ email_address: z.string().email().nullable(),
39
+ personable_type: z.string(),
40
+ title: z.string().nullable(),
41
+ bio: z.string().nullable(),
42
+ location: z.string().nullable(),
43
+ created_at: IsoDateTimeSchema,
44
+ updated_at: IsoDateTimeSchema,
45
+ admin: z.boolean(),
46
+ owner: z.boolean(),
47
+ client: z.boolean(),
48
+ employee: z.boolean(),
49
+ time_zone: z.string(),
50
+ avatar_url: z.string().url(),
51
+ company: z.object({
52
+ id: BasecampIdSchema,
53
+ name: z.string()
54
+ }).optional(),
55
+ can_manage_projects: z.boolean(),
56
+ can_manage_people: z.boolean()
57
+ });
58
+
59
+ // src/contract/schemas/communications/message-boards.ts
60
+ import { z as z2 } from "zod";
61
+ var MessageBoardRecordingCoreSchema = z2.object({
62
+ id: BasecampIdSchema,
63
+ status: RecordingStatusSchema,
64
+ visible_to_clients: z2.boolean(),
65
+ created_at: IsoDateTimeSchema,
66
+ updated_at: IsoDateTimeSchema,
67
+ title: z2.string(),
68
+ inherits_status: z2.boolean(),
69
+ type: z2.string(),
70
+ url: z2.string().url(),
71
+ app_url: z2.string().url(),
72
+ bookmark_url: z2.string().url().optional(),
73
+ position: z2.number().int().nonnegative().optional(),
74
+ bucket: BucketRefSchema,
75
+ creator: PersonSummarySchema
76
+ });
77
+ var MessageBoardSchema = MessageBoardRecordingCoreSchema.extend({
78
+ messages_count: z2.number().int().nonnegative(),
79
+ messages_url: z2.string().url(),
80
+ app_messages_url: z2.string().url()
81
+ });
82
+ var MessageBoardsResponseSchema = z2.array(MessageBoardSchema);
83
+
84
+ // src/contract/resources/communications/message-boards.ts
85
+ var bucketAndMessageBoardPathParams = z3.object({
86
+ bucketId: BasecampIdParamSchema,
87
+ messageBoardId: BasecampIdParamSchema
88
+ });
89
+ var projectPathParams = z3.object({
90
+ projectId: BasecampIdParamSchema
91
+ });
92
+ var messageBoardsRouter = c.router({
93
+ get: {
94
+ summary: "Get a message board",
95
+ description: "Return a message board container for a project.",
96
+ metadata: {
97
+ tag: "Message Boards",
98
+ operationId: "messageBoards.get",
99
+ docsPath: "/docs/basecamp-api-specs/sections/message_boards.md#get-message-board"
100
+ },
101
+ method: "GET",
102
+ path: "/buckets/:bucketId/message_boards/:messageBoardId",
103
+ pathParams: bucketAndMessageBoardPathParams,
104
+ responses: {
105
+ 200: MessageBoardSchema
106
+ }
107
+ },
108
+ listForProject: {
109
+ summary: "List message boards for a project",
110
+ description: "Return message boards available for a project.",
111
+ metadata: {
112
+ tag: "Message Boards",
113
+ operationId: "messageBoards.listForProject",
114
+ docsPath: "/docs/basecamp-api-specs/sections/message_boards.md#get-message-board"
115
+ },
116
+ method: "GET",
117
+ path: "/projects/:projectId/message_boards",
118
+ pathParams: projectPathParams,
119
+ responses: {
120
+ 200: MessageBoardsResponseSchema
121
+ }
122
+ }
123
+ });
124
+
125
+ // src/contract/resources/communications/message-types.ts
126
+ import { z as z5 } from "zod";
127
+
128
+ // src/contract/schemas/communications/message-types.ts
129
+ import { z as z4 } from "zod";
130
+ var MessageTypeSchema = z4.object({
131
+ id: BasecampIdSchema,
132
+ name: z4.string(),
133
+ icon: z4.string(),
134
+ created_at: IsoDateTimeSchema,
135
+ updated_at: IsoDateTimeSchema
136
+ });
137
+ var MessageTypesResponseSchema = z4.array(MessageTypeSchema);
138
+ var MessageTypeCreateBodySchema = z4.object({
139
+ name: z4.string().min(1),
140
+ icon: z4.string().min(1)
141
+ });
142
+ var MessageTypeUpdateBodySchema = z4.object({
143
+ name: z4.string().min(1).optional(),
144
+ icon: z4.string().min(1).optional()
145
+ });
146
+
147
+ // src/contract/resources/communications/message-types.ts
148
+ var bucketPathParams = z5.object({
149
+ bucketId: BasecampIdParamSchema
150
+ });
151
+ var bucketAndCategoryPathParams = bucketPathParams.extend({
152
+ categoryId: BasecampIdParamSchema
153
+ });
154
+ var messageTypesRouter = c.router({
155
+ list: {
156
+ summary: "List message types",
157
+ description: "Return all message types (categories) available in a project.",
158
+ metadata: {
159
+ tag: "Message Types",
160
+ operationId: "messageTypes.list",
161
+ docsPath: "/docs/basecamp-api-specs/sections/message_types.md#get-message-types"
162
+ },
163
+ method: "GET",
164
+ path: "/buckets/:bucketId/categories",
165
+ pathParams: bucketPathParams,
166
+ responses: {
167
+ 200: MessageTypesResponseSchema
168
+ }
169
+ },
170
+ get: {
171
+ summary: "Get a message type",
172
+ description: "Return a specific message type by its ID.",
173
+ metadata: {
174
+ tag: "Message Types",
175
+ operationId: "messageTypes.get",
176
+ docsPath: "/docs/basecamp-api-specs/sections/message_types.md#get-a-message-type"
177
+ },
178
+ method: "GET",
179
+ path: "/buckets/:bucketId/categories/:categoryId",
180
+ pathParams: bucketAndCategoryPathParams,
181
+ responses: {
182
+ 200: MessageTypeSchema
183
+ }
184
+ },
185
+ create: {
186
+ summary: "Create a message type",
187
+ description: "Create a new message type in a project.",
188
+ metadata: {
189
+ tag: "Message Types",
190
+ operationId: "messageTypes.create",
191
+ docsPath: "/docs/basecamp-api-specs/sections/message_types.md#create-a-message-type"
192
+ },
193
+ method: "POST",
194
+ path: "/buckets/:bucketId/categories",
195
+ pathParams: bucketPathParams,
196
+ body: MessageTypeCreateBodySchema,
197
+ responses: {
198
+ 201: MessageTypeSchema
199
+ }
200
+ },
201
+ update: {
202
+ summary: "Update a message type",
203
+ description: "Update an existing message type.",
204
+ metadata: {
205
+ tag: "Message Types",
206
+ operationId: "messageTypes.update",
207
+ docsPath: "/docs/basecamp-api-specs/sections/message_types.md#update-a-message-type"
208
+ },
209
+ method: "PUT",
210
+ path: "/buckets/:bucketId/categories/:categoryId",
211
+ pathParams: bucketAndCategoryPathParams,
212
+ body: MessageTypeUpdateBodySchema,
213
+ responses: {
214
+ 200: MessageTypeSchema
215
+ }
216
+ },
217
+ destroy: {
218
+ summary: "Delete a message type",
219
+ description: "Delete a message type from a project.",
220
+ metadata: {
221
+ tag: "Message Types",
222
+ operationId: "messageTypes.destroy",
223
+ docsPath: "/docs/basecamp-api-specs/sections/message_types.md#destroy-a-message-type"
224
+ },
225
+ method: "DELETE",
226
+ path: "/buckets/:bucketId/categories/:categoryId",
227
+ pathParams: bucketAndCategoryPathParams,
228
+ body: c.noBody(),
229
+ responses: {
230
+ 204: c.noBody()
231
+ }
232
+ }
233
+ });
234
+
235
+ // src/contract/resources/communications/messages.ts
236
+ import { z as z7 } from "zod";
237
+
238
+ // src/contract/schemas/communications/messages.ts
239
+ import { z as z6 } from "zod";
240
+ var MessageCoreSchema = z6.object({
241
+ id: BasecampIdSchema,
242
+ status: RecordingStatusSchema,
243
+ visible_to_clients: z6.boolean(),
244
+ created_at: IsoDateTimeSchema,
245
+ updated_at: IsoDateTimeSchema,
246
+ inherits_status: z6.boolean(),
247
+ type: z6.string(),
248
+ url: z6.string().url(),
249
+ app_url: z6.string().url(),
250
+ bookmark_url: z6.string().url().optional(),
251
+ subscription_url: z6.string().url().optional(),
252
+ comments_count: z6.number().int().nonnegative().optional(),
253
+ comments_url: z6.string().url().optional(),
254
+ parent: RecordingRefSchema.optional(),
255
+ bucket: BucketRefSchema,
256
+ creator: PersonSummarySchema
257
+ });
258
+ var MessageSummarySchema = MessageCoreSchema.extend({
259
+ title: z6.string(),
260
+ content: HtmlStringSchema.optional()
261
+ });
262
+ var MessageSchema = MessageSummarySchema.extend({
263
+ subject: z6.string()
264
+ });
265
+ var MessageListResponseSchema = z6.array(MessageSummarySchema);
266
+ var MessageListQuerySchema = z6.object({
267
+ page: z6.coerce.number().int().positive().optional()
268
+ });
269
+ var MessageCreateBodySchema = z6.object({
270
+ subject: z6.string().min(1),
271
+ status: z6.enum(["active", "draft"]).or(z6.string()),
272
+ content: HtmlStringSchema.optional(),
273
+ category_id: BasecampIdSchema.optional(),
274
+ subscriptions: z6.array(BasecampIdSchema).optional()
275
+ });
276
+ var MessageUpdateBodySchema = z6.object({
277
+ subject: z6.string().min(1).optional(),
278
+ content: HtmlStringSchema.optional(),
279
+ category_id: BasecampIdSchema.optional()
280
+ }).refine(
281
+ (value) => Object.keys(value).length > 0,
282
+ "At least one field must be provided to update a message."
283
+ );
284
+
285
+ // src/contract/resources/communications/messages.ts
286
+ var bucketAndBoardPathParams = z7.object({
287
+ bucketId: BasecampIdParamSchema,
288
+ messageBoardId: BasecampIdParamSchema
289
+ });
290
+ var bucketAndMessagePathParams = z7.object({
291
+ bucketId: BasecampIdParamSchema,
292
+ messageId: BasecampIdParamSchema
293
+ });
294
+ var messagesRouter = c.router({
295
+ list: {
296
+ summary: "List message board messages",
297
+ description: "Returns the messages currently visible on a message board. Pagination data is available via the Link and X-Total-Count headers.",
298
+ metadata: {
299
+ tag: "Messages",
300
+ operationId: "messages.list",
301
+ docsPath: "/docs/basecamp-api-specs/sections/messages.md#get-messages"
302
+ },
303
+ method: "GET",
304
+ path: "/buckets/:bucketId/message_boards/:messageBoardId/messages",
305
+ pathParams: bucketAndBoardPathParams,
306
+ query: MessageListQuerySchema,
307
+ responses: {
308
+ 200: MessageListResponseSchema
309
+ }
310
+ },
311
+ get: {
312
+ summary: "Get a message",
313
+ description: "Fetch the full representation of a single message.",
314
+ metadata: {
315
+ tag: "Messages",
316
+ operationId: "messages.get",
317
+ docsPath: "/docs/basecamp-api-specs/sections/messages.md#get-a-message"
318
+ },
319
+ method: "GET",
320
+ path: "/buckets/:bucketId/messages/:messageId",
321
+ pathParams: bucketAndMessagePathParams,
322
+ responses: {
323
+ 200: MessageSchema
324
+ }
325
+ },
326
+ create: {
327
+ summary: "Create a message",
328
+ description: 'Publish a message to a specific message board. Setting status to "active" makes the message visible immediately.',
329
+ metadata: {
330
+ tag: "Messages",
331
+ operationId: "messages.create",
332
+ docsPath: "/docs/basecamp-api-specs/sections/messages.md#create-a-message"
333
+ },
334
+ method: "POST",
335
+ path: "/buckets/:bucketId/message_boards/:messageBoardId/messages",
336
+ pathParams: bucketAndBoardPathParams,
337
+ body: MessageCreateBodySchema,
338
+ responses: {
339
+ 201: MessageSchema
340
+ }
341
+ },
342
+ update: {
343
+ summary: "Update a message",
344
+ description: "Update the subject, content, or category of an existing message.",
345
+ metadata: {
346
+ tag: "Messages",
347
+ operationId: "messages.update",
348
+ docsPath: "/docs/basecamp-api-specs/sections/messages.md#update-a-message"
349
+ },
350
+ method: "PUT",
351
+ path: "/buckets/:bucketId/messages/:messageId",
352
+ pathParams: bucketAndMessagePathParams,
353
+ body: MessageUpdateBodySchema,
354
+ responses: {
355
+ 200: MessageSchema
356
+ }
357
+ },
358
+ pin: {
359
+ summary: "Pin a message",
360
+ description: "Pin a message recording. The same endpoint is used to pin other recording types.",
361
+ metadata: {
362
+ tag: "Messages",
363
+ operationId: "messages.pin",
364
+ docsPath: "/docs/basecamp-api-specs/sections/messages.md#pin-a-message"
365
+ },
366
+ method: "POST",
367
+ path: "/buckets/:bucketId/recordings/:messageId/pin",
368
+ pathParams: bucketAndMessagePathParams,
369
+ body: c.noBody(),
370
+ responses: {
371
+ 204: c.noBody()
372
+ }
373
+ },
374
+ unpin: {
375
+ summary: "Unpin a message",
376
+ description: "Remove a pinned message. Returns no content on success.",
377
+ metadata: {
378
+ tag: "Messages",
379
+ operationId: "messages.unpin",
380
+ docsPath: "/docs/basecamp-api-specs/sections/messages.md#pin-a-message"
381
+ },
382
+ method: "DELETE",
383
+ path: "/buckets/:bucketId/recordings/:messageId/pin",
384
+ pathParams: bucketAndMessagePathParams,
385
+ body: c.noBody(),
386
+ responses: {
387
+ 204: c.noBody()
388
+ }
389
+ },
390
+ trash: {
391
+ summary: "Trash a message",
392
+ description: "Move a message recording to the trash. Trashed items can be restored via the UI.",
393
+ metadata: {
394
+ tag: "Messages",
395
+ operationId: "messages.trash",
396
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
397
+ },
398
+ method: "PUT",
399
+ path: "/buckets/:bucketId/recordings/:messageId/status/trashed",
400
+ pathParams: bucketAndMessagePathParams,
401
+ body: c.noBody(),
402
+ responses: {
403
+ 204: c.noBody()
404
+ }
405
+ }
406
+ });
407
+
408
+ // src/contract/resources/communications/comments.ts
409
+ import { z as z9 } from "zod";
410
+
411
+ // src/contract/schemas/communications/comments.ts
412
+ import { z as z8 } from "zod";
413
+ var CommentRecordingCoreSchema = z8.object({
414
+ id: BasecampIdSchema,
415
+ status: RecordingStatusSchema,
416
+ visible_to_clients: z8.boolean(),
417
+ created_at: IsoDateTimeSchema,
418
+ updated_at: IsoDateTimeSchema,
419
+ title: z8.string(),
420
+ inherits_status: z8.boolean(),
421
+ type: z8.string(),
422
+ url: z8.string().url(),
423
+ app_url: z8.string().url(),
424
+ bookmark_url: z8.string().url().optional(),
425
+ parent: RecordingRefSchema.optional(),
426
+ bucket: BucketRefSchema,
427
+ creator: PersonSummarySchema
428
+ });
429
+ var CommentSchema = CommentRecordingCoreSchema.extend({
430
+ content: HtmlStringSchema
431
+ });
432
+ var CommentsResponseSchema = z8.array(CommentSchema);
433
+ var CommentListQuerySchema = z8.object({
434
+ page: z8.coerce.number().int().positive().optional()
435
+ });
436
+ var CommentCreateBodySchema = z8.object({
437
+ content: HtmlStringSchema.min(1)
438
+ });
439
+ var CommentUpdateBodySchema = z8.object({
440
+ content: HtmlStringSchema.min(1)
441
+ });
442
+
443
+ // src/contract/resources/communications/comments.ts
444
+ var bucketAndRecordingPathParams = z9.object({
445
+ bucketId: BasecampIdParamSchema,
446
+ recordingId: BasecampIdParamSchema
447
+ });
448
+ var bucketAndCommentPathParams = z9.object({
449
+ bucketId: BasecampIdParamSchema,
450
+ commentId: BasecampIdParamSchema
451
+ });
452
+ var commentsRouter = c.router({
453
+ list: {
454
+ summary: "List comments",
455
+ description: "Return paginated comments for a recording.",
456
+ metadata: {
457
+ tag: "Comments",
458
+ operationId: "comments.list",
459
+ docsPath: "/docs/basecamp-api-specs/sections/comments.md#get-comments"
460
+ },
461
+ method: "GET",
462
+ path: "/buckets/:bucketId/recordings/:recordingId/comments",
463
+ pathParams: bucketAndRecordingPathParams,
464
+ query: CommentListQuerySchema,
465
+ responses: {
466
+ 200: CommentsResponseSchema
467
+ }
468
+ },
469
+ get: {
470
+ summary: "Get a comment",
471
+ description: "Return a specific comment by its ID.",
472
+ metadata: {
473
+ tag: "Comments",
474
+ operationId: "comments.get",
475
+ docsPath: "/docs/basecamp-api-specs/sections/comments.md#get-a-comment"
476
+ },
477
+ method: "GET",
478
+ path: "/buckets/:bucketId/comments/:commentId",
479
+ pathParams: bucketAndCommentPathParams,
480
+ responses: {
481
+ 200: CommentSchema
482
+ }
483
+ },
484
+ create: {
485
+ summary: "Create a comment",
486
+ description: "Create a new comment on a recording.",
487
+ metadata: {
488
+ tag: "Comments",
489
+ operationId: "comments.create",
490
+ docsPath: "/docs/basecamp-api-specs/sections/comments.md#create-a-comment"
491
+ },
492
+ method: "POST",
493
+ path: "/buckets/:bucketId/recordings/:recordingId/comments",
494
+ pathParams: bucketAndRecordingPathParams,
495
+ body: CommentCreateBodySchema,
496
+ responses: {
497
+ 201: CommentSchema
498
+ }
499
+ },
500
+ update: {
501
+ summary: "Update a comment",
502
+ description: "Update an existing comment.",
503
+ metadata: {
504
+ tag: "Comments",
505
+ operationId: "comments.update",
506
+ docsPath: "/docs/basecamp-api-specs/sections/comments.md#update-a-comment"
507
+ },
508
+ method: "PUT",
509
+ path: "/buckets/:bucketId/comments/:commentId",
510
+ pathParams: bucketAndCommentPathParams,
511
+ body: CommentUpdateBodySchema,
512
+ responses: {
513
+ 200: CommentSchema
514
+ }
515
+ },
516
+ trash: {
517
+ summary: "Trash a comment",
518
+ description: "Move a comment to the trash.",
519
+ metadata: {
520
+ tag: "Comments",
521
+ operationId: "comments.trash",
522
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
523
+ },
524
+ method: "PUT",
525
+ path: "/buckets/:bucketId/recordings/:commentId/status/trashed",
526
+ pathParams: bucketAndCommentPathParams,
527
+ body: c.noBody(),
528
+ responses: {
529
+ 204: c.noBody()
530
+ }
531
+ }
532
+ });
533
+
534
+ // src/contract/resources/communications/campfires.ts
535
+ import { z as z11 } from "zod";
536
+
537
+ // src/contract/schemas/communications/campfires.ts
538
+ import { z as z10 } from "zod";
539
+ var CampfireSchema = z10.object({
540
+ id: BasecampIdSchema,
541
+ status: RecordingStatusSchema,
542
+ visible_to_clients: z10.boolean(),
543
+ created_at: IsoDateTimeSchema,
544
+ updated_at: IsoDateTimeSchema,
545
+ title: z10.string(),
546
+ inherits_status: z10.boolean(),
547
+ type: z10.string(),
548
+ url: z10.string().url(),
549
+ app_url: z10.string().url(),
550
+ bookmark_url: z10.string().url().optional(),
551
+ subscription_url: z10.string().url().optional(),
552
+ position: z10.number().int().optional(),
553
+ topic: z10.string(),
554
+ lines_url: z10.string().url(),
555
+ bucket: BucketRefSchema,
556
+ creator: PersonSummarySchema
557
+ });
558
+ var CampfireListResponseSchema = z10.array(CampfireSchema);
559
+ var CampfireListQuerySchema = z10.object({
560
+ page: z10.coerce.number().int().positive().optional()
561
+ });
562
+ var CampfireLineSchema = z10.object({
563
+ id: BasecampIdSchema,
564
+ status: RecordingStatusSchema,
565
+ visible_to_clients: z10.boolean(),
566
+ created_at: IsoDateTimeSchema,
567
+ updated_at: IsoDateTimeSchema,
568
+ title: z10.string(),
569
+ inherits_status: z10.boolean(),
570
+ type: z10.string(),
571
+ url: z10.string().url(),
572
+ app_url: z10.string().url(),
573
+ bookmark_url: z10.string().url().optional(),
574
+ parent: RecordingRefSchema,
575
+ bucket: BucketRefSchema,
576
+ creator: PersonSummarySchema,
577
+ content: z10.string()
578
+ });
579
+ var CampfireLineListResponseSchema = z10.array(CampfireLineSchema);
580
+ var CampfireLineListQuerySchema = z10.object({
581
+ page: z10.coerce.number().int().positive().optional()
582
+ });
583
+ var CampfireLineCreateBodySchema = z10.object({
584
+ content: z10.string().min(1)
585
+ });
586
+
587
+ // src/contract/resources/communications/campfires.ts
588
+ var CampfirePathParamsSchema = z11.object({
589
+ bucketId: BasecampIdParamSchema,
590
+ campfireId: BasecampIdParamSchema
591
+ });
592
+ var CampfireLinePathParamsSchema = CampfirePathParamsSchema.extend({
593
+ lineId: BasecampIdParamSchema
594
+ });
595
+ var campfiresRouter = c.router({
596
+ list: {
597
+ summary: "List Campfires",
598
+ description: "Returns the Campfires visible to the authenticated user. Results are paginated via Link headers.",
599
+ metadata: {
600
+ tag: "Campfires",
601
+ operationId: "campfires.list",
602
+ docsPath: "/docs/basecamp-api-specs/sections/campfires.md#get-campfires"
603
+ },
604
+ method: "GET",
605
+ path: "/chats",
606
+ query: CampfireListQuerySchema,
607
+ responses: {
608
+ 200: CampfireListResponseSchema
609
+ }
610
+ },
611
+ get: {
612
+ summary: "Get a Campfire",
613
+ description: "Fetch a single Campfire transcript for a project.",
614
+ metadata: {
615
+ tag: "Campfires",
616
+ operationId: "campfires.get",
617
+ docsPath: "/docs/basecamp-api-specs/sections/campfires.md#get-a-campfire"
618
+ },
619
+ method: "GET",
620
+ path: "/buckets/:bucketId/chats/:campfireId",
621
+ pathParams: CampfirePathParamsSchema,
622
+ responses: {
623
+ 200: CampfireSchema
624
+ }
625
+ },
626
+ listLines: {
627
+ summary: "List Campfire lines",
628
+ description: "Return paginated chat lines for a Campfire transcript.",
629
+ metadata: {
630
+ tag: "Campfires",
631
+ operationId: "campfires.listLines",
632
+ docsPath: "/docs/basecamp-api-specs/sections/campfires.md#get-campfire-lines"
633
+ },
634
+ method: "GET",
635
+ path: "/buckets/:bucketId/chats/:campfireId/lines",
636
+ pathParams: CampfirePathParamsSchema,
637
+ query: CampfireLineListQuerySchema,
638
+ responses: {
639
+ 200: CampfireLineListResponseSchema
640
+ }
641
+ },
642
+ getLine: {
643
+ summary: "Get a Campfire line",
644
+ description: "Fetch a single Campfire line by identifier.",
645
+ metadata: {
646
+ tag: "Campfires",
647
+ operationId: "campfires.getLine",
648
+ docsPath: "/docs/basecamp-api-specs/sections/campfires.md#get-a-campfire-line"
649
+ },
650
+ method: "GET",
651
+ path: "/buckets/:bucketId/chats/:campfireId/lines/:lineId",
652
+ pathParams: CampfireLinePathParamsSchema,
653
+ responses: {
654
+ 200: CampfireLineSchema
655
+ }
656
+ },
657
+ createLine: {
658
+ summary: "Create a Campfire line",
659
+ description: "Post a new line of chat to a Campfire transcript.",
660
+ metadata: {
661
+ tag: "Campfires",
662
+ operationId: "campfires.createLine",
663
+ docsPath: "/docs/basecamp-api-specs/sections/campfires.md#create-a-campfire-line"
664
+ },
665
+ method: "POST",
666
+ path: "/buckets/:bucketId/chats/:campfireId/lines",
667
+ pathParams: CampfirePathParamsSchema,
668
+ body: CampfireLineCreateBodySchema,
669
+ responses: {
670
+ 201: CampfireLineSchema
671
+ }
672
+ },
673
+ deleteLine: {
674
+ summary: "Delete a Campfire line",
675
+ description: "Delete a Campfire line permanently.",
676
+ metadata: {
677
+ tag: "Campfires",
678
+ operationId: "campfires.deleteLine",
679
+ docsPath: "/docs/basecamp-api-specs/sections/campfires.md#delete-a-campfire-line"
680
+ },
681
+ method: "DELETE",
682
+ path: "/buckets/:bucketId/chats/:campfireId/lines/:lineId",
683
+ pathParams: CampfireLinePathParamsSchema,
684
+ body: c.noBody(),
685
+ responses: {
686
+ 204: c.noBody()
687
+ }
688
+ }
689
+ });
690
+
691
+ // src/contract/resources/communications/inboxes.ts
692
+ import { z as z13 } from "zod";
693
+
694
+ // src/contract/schemas/communications/inboxes.ts
695
+ import { z as z12 } from "zod";
696
+ var InboxSchema = z12.object({
697
+ id: BasecampIdSchema,
698
+ status: RecordingStatusSchema,
699
+ visible_to_clients: z12.boolean(),
700
+ created_at: IsoDateTimeSchema,
701
+ updated_at: IsoDateTimeSchema,
702
+ title: z12.string(),
703
+ inherits_status: z12.boolean(),
704
+ type: z12.string(),
705
+ url: z12.string().url(),
706
+ app_url: z12.string().url(),
707
+ bookmark_url: z12.string().url().optional(),
708
+ position: z12.number().int().optional(),
709
+ forwards_count: z12.number().int().nonnegative().optional(),
710
+ forwards_url: z12.string().url().optional(),
711
+ bucket: BucketRefSchema,
712
+ creator: PersonSummarySchema
713
+ });
714
+
715
+ // src/contract/resources/communications/inboxes.ts
716
+ var InboxPathParamsSchema = z13.object({
717
+ bucketId: BasecampIdParamSchema,
718
+ inboxId: BasecampIdParamSchema
719
+ });
720
+ var inboxesRouter = c.router({
721
+ get: {
722
+ summary: "Get an inbox",
723
+ description: "Return the inbox container for a project. Use the forwards endpoint to list mail forwards associated with the inbox.",
724
+ metadata: {
725
+ tag: "Inboxes",
726
+ operationId: "inboxes.get",
727
+ docsPath: "/docs/basecamp-api-specs/sections/inboxes.md#get-inbox"
728
+ },
729
+ method: "GET",
730
+ path: "/buckets/:bucketId/inboxes/:inboxId",
731
+ pathParams: InboxPathParamsSchema,
732
+ responses: {
733
+ 200: InboxSchema
734
+ }
735
+ }
736
+ });
737
+
738
+ // src/contract/resources/communications/forwards.ts
739
+ import { z as z15 } from "zod";
740
+
741
+ // src/contract/schemas/communications/forwards.ts
742
+ import { z as z14 } from "zod";
743
+ var ForwardSchema = z14.object({
744
+ id: BasecampIdSchema,
745
+ status: RecordingStatusSchema,
746
+ visible_to_clients: z14.boolean(),
747
+ created_at: IsoDateTimeSchema,
748
+ updated_at: IsoDateTimeSchema,
749
+ title: z14.string(),
750
+ inherits_status: z14.boolean(),
751
+ type: z14.string(),
752
+ url: z14.string().url(),
753
+ app_url: z14.string().url(),
754
+ bookmark_url: z14.string().url().optional(),
755
+ subscription_url: z14.string().url().optional(),
756
+ parent: RecordingRefSchema,
757
+ bucket: BucketRefSchema,
758
+ creator: PersonSummarySchema,
759
+ content: z14.string(),
760
+ subject: z14.string(),
761
+ from: z14.string().nullable().optional(),
762
+ replies_count: z14.number().int().nonnegative(),
763
+ replies_url: z14.string().url()
764
+ });
765
+ var ForwardListResponseSchema = z14.array(ForwardSchema);
766
+ var ForwardListQuerySchema = z14.object({
767
+ page: z14.coerce.number().int().positive().optional()
768
+ });
769
+
770
+ // src/contract/resources/communications/forwards.ts
771
+ var ForwardListPathParamsSchema = z15.object({
772
+ bucketId: BasecampIdParamSchema,
773
+ inboxId: BasecampIdParamSchema
774
+ });
775
+ var ForwardPathParamsSchema = z15.object({
776
+ bucketId: BasecampIdParamSchema,
777
+ forwardId: BasecampIdParamSchema
778
+ });
779
+ var forwardsRouter = c.router({
780
+ list: {
781
+ summary: "List forwards",
782
+ description: "Returns the email forwards that live under a project inbox. Results are paginated via Link headers.",
783
+ metadata: {
784
+ tag: "Forwards",
785
+ operationId: "forwards.list",
786
+ docsPath: "/docs/basecamp-api-specs/sections/forwards.md#get-forwards"
787
+ },
788
+ method: "GET",
789
+ path: "/buckets/:bucketId/inboxes/:inboxId/forwards",
790
+ pathParams: ForwardListPathParamsSchema,
791
+ query: ForwardListQuerySchema,
792
+ responses: {
793
+ 200: ForwardListResponseSchema
794
+ }
795
+ },
796
+ get: {
797
+ summary: "Get a forward",
798
+ description: "Fetch a single email forward recording.",
799
+ metadata: {
800
+ tag: "Forwards",
801
+ operationId: "forwards.get",
802
+ docsPath: "/docs/basecamp-api-specs/sections/forwards.md#get-a-forward"
803
+ },
804
+ method: "GET",
805
+ path: "/buckets/:bucketId/inbox_forwards/:forwardId",
806
+ pathParams: ForwardPathParamsSchema,
807
+ responses: {
808
+ 200: ForwardSchema
809
+ }
810
+ },
811
+ trash: {
812
+ summary: "Trash a forward",
813
+ description: "Move a forward to the trash. Trashed forwards can be restored from the Basecamp UI if needed.",
814
+ metadata: {
815
+ tag: "Forwards",
816
+ operationId: "forwards.trash",
817
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
818
+ },
819
+ method: "PUT",
820
+ path: "/buckets/:bucketId/recordings/:forwardId/status/trashed",
821
+ pathParams: ForwardPathParamsSchema,
822
+ body: c.noBody(),
823
+ responses: {
824
+ 204: c.noBody()
825
+ }
826
+ }
827
+ });
828
+
829
+ // src/contract/resources/communications/inbox-replies.ts
830
+ import { z as z17 } from "zod";
831
+
832
+ // src/contract/schemas/communications/inbox-replies.ts
833
+ import { z as z16 } from "zod";
834
+ var InboxReplySchema = z16.object({
835
+ id: BasecampIdSchema,
836
+ status: RecordingStatusSchema,
837
+ visible_to_clients: z16.boolean(),
838
+ created_at: IsoDateTimeSchema,
839
+ updated_at: IsoDateTimeSchema,
840
+ title: z16.string(),
841
+ inherits_status: z16.boolean(),
842
+ type: z16.string(),
843
+ url: z16.string().url(),
844
+ app_url: z16.string().url(),
845
+ bookmark_url: z16.string().url().optional(),
846
+ parent: RecordingRefSchema,
847
+ bucket: BucketRefSchema,
848
+ creator: PersonSummarySchema,
849
+ content: HtmlStringSchema
850
+ });
851
+ var InboxReplyListResponseSchema = z16.array(InboxReplySchema);
852
+ var InboxReplyListQuerySchema = z16.object({
853
+ page: z16.coerce.number().int().positive().optional()
854
+ });
855
+
856
+ // src/contract/resources/communications/inbox-replies.ts
857
+ var InboxReplyListPathParamsSchema = z17.object({
858
+ bucketId: BasecampIdParamSchema,
859
+ forwardId: BasecampIdParamSchema
860
+ });
861
+ var InboxReplyPathParamsSchema = InboxReplyListPathParamsSchema.extend({
862
+ replyId: BasecampIdParamSchema
863
+ });
864
+ var inboxRepliesRouter = c.router({
865
+ list: {
866
+ summary: "List inbox replies",
867
+ description: "Returns replies that were posted on a forwarded email.",
868
+ metadata: {
869
+ tag: "Inbox Replies",
870
+ operationId: "inboxReplies.list",
871
+ docsPath: "/docs/basecamp-api-specs/sections/inbox_replies.md#get-inbox-replies"
872
+ },
873
+ method: "GET",
874
+ path: "/buckets/:bucketId/inbox_forwards/:forwardId/replies",
875
+ pathParams: InboxReplyListPathParamsSchema,
876
+ query: InboxReplyListQuerySchema,
877
+ responses: {
878
+ 200: InboxReplyListResponseSchema
879
+ }
880
+ },
881
+ get: {
882
+ summary: "Get an inbox reply",
883
+ description: "Fetch a single reply posted to a forwarded email.",
884
+ metadata: {
885
+ tag: "Inbox Replies",
886
+ operationId: "inboxReplies.get",
887
+ docsPath: "/docs/basecamp-api-specs/sections/inbox_replies.md#get-an-inbox-reply"
888
+ },
889
+ method: "GET",
890
+ path: "/buckets/:bucketId/inbox_forwards/:forwardId/replies/:replyId",
891
+ pathParams: InboxReplyPathParamsSchema,
892
+ responses: {
893
+ 200: InboxReplySchema
894
+ }
895
+ }
896
+ });
897
+
898
+ // src/contract/resources/communications/client-approvals.ts
899
+ import { z as z19 } from "zod";
900
+
901
+ // src/contract/schemas/communications/client-approvals.ts
902
+ import { z as z18 } from "zod";
903
+ var ApprovalStatusEnum = z18.enum(["pending", "approved", "rejected"]).or(z18.string());
904
+ var ClientApprovalResponseSchema = z18.object({
905
+ id: BasecampIdSchema,
906
+ status: RecordingStatusSchema,
907
+ visible_to_clients: z18.boolean(),
908
+ created_at: IsoDateTimeSchema,
909
+ updated_at: IsoDateTimeSchema,
910
+ title: z18.string(),
911
+ inherits_status: z18.boolean(),
912
+ type: z18.string(),
913
+ url: z18.string().url().optional(),
914
+ app_url: z18.string().url(),
915
+ bookmark_url: z18.string().url().optional(),
916
+ parent: RecordingRefSchema,
917
+ bucket: BucketRefSchema,
918
+ creator: PersonSummarySchema,
919
+ content: HtmlStringSchema,
920
+ approved: z18.boolean().optional()
921
+ });
922
+ var ClientApprovalSchema = z18.object({
923
+ id: BasecampIdSchema,
924
+ status: RecordingStatusSchema,
925
+ visible_to_clients: z18.boolean(),
926
+ created_at: IsoDateTimeSchema,
927
+ updated_at: IsoDateTimeSchema,
928
+ title: z18.string(),
929
+ inherits_status: z18.boolean(),
930
+ type: z18.string(),
931
+ url: z18.string().url(),
932
+ app_url: z18.string().url(),
933
+ bookmark_url: z18.string().url().optional(),
934
+ subscription_url: z18.string().url().optional(),
935
+ parent: RecordingRefSchema,
936
+ bucket: BucketRefSchema,
937
+ creator: PersonSummarySchema,
938
+ content: HtmlStringSchema,
939
+ subject: z18.string(),
940
+ due_on: IsoDateSchema.nullable(),
941
+ replies_count: z18.number().int().nonnegative(),
942
+ replies_url: z18.string().url(),
943
+ approval_status: ApprovalStatusEnum,
944
+ approver: PersonSummarySchema.optional(),
945
+ responses: z18.array(ClientApprovalResponseSchema).optional()
946
+ });
947
+ var ClientApprovalListResponseSchema = z18.array(ClientApprovalSchema);
948
+ var ClientApprovalListQuerySchema = z18.object({
949
+ page: z18.coerce.number().int().positive().optional()
950
+ });
951
+
952
+ // src/contract/resources/communications/client-approvals.ts
953
+ var ClientApprovalListPathParamsSchema = z19.object({
954
+ bucketId: BasecampIdParamSchema
955
+ });
956
+ var ClientApprovalPathParamsSchema = ClientApprovalListPathParamsSchema.extend({
957
+ approvalId: BasecampIdParamSchema
958
+ });
959
+ var clientApprovalsRouter = c.router({
960
+ list: {
961
+ summary: "List client approvals",
962
+ description: "Returns the client approvals that have been posted in a project. Results are paginated.",
963
+ metadata: {
964
+ tag: "Client Approvals",
965
+ operationId: "clientApprovals.list",
966
+ docsPath: "/docs/basecamp-api-specs/sections/client_approvals.md#get-client-approvals"
967
+ },
968
+ method: "GET",
969
+ path: "/buckets/:bucketId/client/approvals",
970
+ pathParams: ClientApprovalListPathParamsSchema,
971
+ query: ClientApprovalListQuerySchema,
972
+ responses: {
973
+ 200: ClientApprovalListResponseSchema
974
+ }
975
+ },
976
+ get: {
977
+ summary: "Get a client approval",
978
+ description: "Fetch a specific client approval recording.",
979
+ metadata: {
980
+ tag: "Client Approvals",
981
+ operationId: "clientApprovals.get",
982
+ docsPath: "/docs/basecamp-api-specs/sections/client_approvals.md#get-a-client-approval"
983
+ },
984
+ method: "GET",
985
+ path: "/buckets/:bucketId/client/approvals/:approvalId",
986
+ pathParams: ClientApprovalPathParamsSchema,
987
+ responses: {
988
+ 200: ClientApprovalSchema
989
+ }
990
+ }
991
+ });
992
+
993
+ // src/contract/resources/communications/client-correspondences.ts
994
+ import { z as z21 } from "zod";
995
+
996
+ // src/contract/schemas/communications/client-correspondences.ts
997
+ import { z as z20 } from "zod";
998
+ var ClientCorrespondenceSchema = z20.object({
999
+ id: BasecampIdSchema,
1000
+ status: RecordingStatusSchema,
1001
+ visible_to_clients: z20.boolean(),
1002
+ created_at: IsoDateTimeSchema,
1003
+ updated_at: IsoDateTimeSchema,
1004
+ title: z20.string(),
1005
+ inherits_status: z20.boolean(),
1006
+ type: z20.string(),
1007
+ url: z20.string().url(),
1008
+ app_url: z20.string().url(),
1009
+ bookmark_url: z20.string().url().optional(),
1010
+ subscription_url: z20.string().url().optional(),
1011
+ parent: RecordingRefSchema,
1012
+ bucket: BucketRefSchema,
1013
+ creator: PersonSummarySchema,
1014
+ content: HtmlStringSchema,
1015
+ subject: z20.string(),
1016
+ replies_count: z20.number().int().nonnegative(),
1017
+ replies_url: z20.string().url()
1018
+ });
1019
+ var ClientCorrespondenceListResponseSchema = z20.array(ClientCorrespondenceSchema);
1020
+ var ClientCorrespondenceListQuerySchema = z20.object({
1021
+ page: z20.coerce.number().int().positive().optional()
1022
+ });
1023
+
1024
+ // src/contract/resources/communications/client-correspondences.ts
1025
+ var ClientCorrespondenceListPathParamsSchema = z21.object({
1026
+ bucketId: BasecampIdParamSchema
1027
+ });
1028
+ var ClientCorrespondencePathParamsSchema = ClientCorrespondenceListPathParamsSchema.extend({
1029
+ correspondenceId: BasecampIdParamSchema
1030
+ });
1031
+ var clientCorrespondencesRouter = c.router({
1032
+ list: {
1033
+ summary: "List client correspondences",
1034
+ description: "Returns the client correspondences posted in a project.",
1035
+ metadata: {
1036
+ tag: "Client Correspondences",
1037
+ operationId: "clientCorrespondences.list",
1038
+ docsPath: "/docs/basecamp-api-specs/sections/client_correspondences.md#get-client-correspondences"
1039
+ },
1040
+ method: "GET",
1041
+ path: "/buckets/:bucketId/client/correspondences",
1042
+ pathParams: ClientCorrespondenceListPathParamsSchema,
1043
+ query: ClientCorrespondenceListQuerySchema,
1044
+ responses: {
1045
+ 200: ClientCorrespondenceListResponseSchema
1046
+ }
1047
+ },
1048
+ get: {
1049
+ summary: "Get a client correspondence",
1050
+ description: "Fetch a specific client correspondence recording.",
1051
+ metadata: {
1052
+ tag: "Client Correspondences",
1053
+ operationId: "clientCorrespondences.get",
1054
+ docsPath: "/docs/basecamp-api-specs/sections/client_correspondences.md#get-a-client-correspondence"
1055
+ },
1056
+ method: "GET",
1057
+ path: "/buckets/:bucketId/client/correspondences/:correspondenceId",
1058
+ pathParams: ClientCorrespondencePathParamsSchema,
1059
+ responses: {
1060
+ 200: ClientCorrespondenceSchema
1061
+ }
1062
+ }
1063
+ });
1064
+
1065
+ // src/contract/resources/communications/client-replies.ts
1066
+ import { z as z23 } from "zod";
1067
+
1068
+ // src/contract/schemas/communications/client-replies.ts
1069
+ import { z as z22 } from "zod";
1070
+ var ClientReplySchema = z22.object({
1071
+ id: BasecampIdSchema,
1072
+ status: RecordingStatusSchema,
1073
+ visible_to_clients: z22.boolean(),
1074
+ created_at: IsoDateTimeSchema,
1075
+ updated_at: IsoDateTimeSchema,
1076
+ title: z22.string(),
1077
+ inherits_status: z22.boolean(),
1078
+ type: z22.string(),
1079
+ url: z22.string().url(),
1080
+ app_url: z22.string().url(),
1081
+ bookmark_url: z22.string().url().optional(),
1082
+ parent: RecordingRefSchema,
1083
+ bucket: BucketRefSchema,
1084
+ creator: PersonSummarySchema,
1085
+ content: HtmlStringSchema
1086
+ });
1087
+ var ClientReplyListResponseSchema = z22.array(ClientReplySchema);
1088
+ var ClientReplyListQuerySchema = z22.object({
1089
+ page: z22.coerce.number().int().positive().optional()
1090
+ });
1091
+
1092
+ // src/contract/resources/communications/client-replies.ts
1093
+ var ClientReplyListPathParamsSchema = z23.object({
1094
+ bucketId: BasecampIdParamSchema,
1095
+ recordingId: BasecampIdParamSchema
1096
+ });
1097
+ var ClientReplyPathParamsSchema = ClientReplyListPathParamsSchema.extend({
1098
+ replyId: BasecampIdParamSchema
1099
+ });
1100
+ var clientRepliesRouter = c.router({
1101
+ list: {
1102
+ summary: "List client replies",
1103
+ description: "Returns replies that clients posted to client correspondences or client approvals.",
1104
+ metadata: {
1105
+ tag: "Client Replies",
1106
+ operationId: "clientReplies.list",
1107
+ docsPath: "/docs/basecamp-api-specs/sections/client_replies.md#get-client-replies"
1108
+ },
1109
+ method: "GET",
1110
+ path: "/buckets/:bucketId/client/recordings/:recordingId/replies",
1111
+ pathParams: ClientReplyListPathParamsSchema,
1112
+ query: ClientReplyListQuerySchema,
1113
+ responses: {
1114
+ 200: ClientReplyListResponseSchema
1115
+ }
1116
+ },
1117
+ get: {
1118
+ summary: "Get a client reply",
1119
+ description: "Fetch a single reply posted by a client.",
1120
+ metadata: {
1121
+ tag: "Client Replies",
1122
+ operationId: "clientReplies.get",
1123
+ docsPath: "/docs/basecamp-api-specs/sections/client_replies.md#get-a-client-reply"
1124
+ },
1125
+ method: "GET",
1126
+ path: "/buckets/:bucketId/client/recordings/:recordingId/replies/:replyId",
1127
+ pathParams: ClientReplyPathParamsSchema,
1128
+ responses: {
1129
+ 200: ClientReplySchema
1130
+ }
1131
+ }
1132
+ });
1133
+
1134
+ // src/contract/resources/communications/client-visibility.ts
1135
+ import { z as z26 } from "zod";
1136
+
1137
+ // src/contract/schemas/communications/client-visibility.ts
1138
+ import { z as z25 } from "zod";
1139
+
1140
+ // src/contract/schemas/recordings.ts
1141
+ import { z as z24 } from "zod";
1142
+ var KnownRecordingTypeSchema = z24.enum([
1143
+ "Comment",
1144
+ "Document",
1145
+ "Kanban::Card",
1146
+ "Kanban::Step",
1147
+ "Message",
1148
+ "Question::Answer",
1149
+ "Schedule::Entry",
1150
+ "Todo",
1151
+ "Todolist",
1152
+ "Upload",
1153
+ "Vault"
1154
+ ]);
1155
+ var RecordingTypeSchema = KnownRecordingTypeSchema.or(z24.string());
1156
+ var RecordingSummarySchema = z24.object({
1157
+ id: BasecampIdSchema,
1158
+ type: z24.string(),
1159
+ status: RecordingStatusSchema.optional(),
1160
+ title: z24.string().optional(),
1161
+ created_at: IsoDateTimeSchema.optional(),
1162
+ updated_at: IsoDateTimeSchema.optional(),
1163
+ url: z24.string().url(),
1164
+ app_url: z24.string().url(),
1165
+ bucket: BucketRefSchema.optional(),
1166
+ parent: RecordingRefSchema.optional(),
1167
+ creator: PersonSummarySchema.optional()
1168
+ }).passthrough();
1169
+ var RecordingListResponseSchema = z24.array(RecordingSummarySchema);
1170
+ var RecordingListQuerySchema = z24.object({
1171
+ type: RecordingTypeSchema,
1172
+ bucket: z24.string().optional(),
1173
+ status: RecordingStatusSchema.optional(),
1174
+ sort: z24.enum(["created_at", "updated_at"]).or(z24.string()).optional(),
1175
+ direction: z24.enum(["asc", "desc"]).or(z24.string()).optional(),
1176
+ page: z24.coerce.number().int().positive().optional()
1177
+ });
1178
+
1179
+ // src/contract/schemas/communications/client-visibility.ts
1180
+ var ClientVisibilityUpdateBodySchema = z25.object({
1181
+ visible_to_clients: z25.boolean()
1182
+ });
1183
+ var ClientVisibilityRecordingSchema = RecordingSummarySchema.extend({
1184
+ visible_to_clients: z25.boolean().optional()
1185
+ });
1186
+
1187
+ // src/contract/resources/communications/client-visibility.ts
1188
+ var ClientVisibilityPathParamsSchema = z26.object({
1189
+ bucketId: BasecampIdParamSchema,
1190
+ recordingId: BasecampIdParamSchema
1191
+ });
1192
+ var clientVisibilityRouter = c.router({
1193
+ update: {
1194
+ summary: "Toggle client visibility",
1195
+ description: "Update whether a recording is visible to clients. Only recordings that control their own visibility can be toggled.",
1196
+ metadata: {
1197
+ tag: "Client Visibility",
1198
+ operationId: "clientVisibility.update",
1199
+ docsPath: "/docs/basecamp-api-specs/sections/client_visibility.md#toggle-client-visibility"
1200
+ },
1201
+ method: "PUT",
1202
+ path: "/buckets/:bucketId/recordings/:recordingId/client_visibility",
1203
+ pathParams: ClientVisibilityPathParamsSchema,
1204
+ body: ClientVisibilityUpdateBodySchema,
1205
+ responses: {
1206
+ 200: ClientVisibilityRecordingSchema
1207
+ }
1208
+ }
1209
+ });
1210
+
1211
+ // src/contract/resources/documents/documents.ts
1212
+ import { z as z31 } from "zod";
1213
+
1214
+ // src/contract/schemas/documents/documents.ts
1215
+ import { z as z27 } from "zod";
1216
+ var DocumentCoreSchema = z27.object({
1217
+ id: BasecampIdSchema,
1218
+ status: RecordingStatusSchema,
1219
+ visible_to_clients: z27.boolean(),
1220
+ created_at: IsoDateTimeSchema,
1221
+ updated_at: IsoDateTimeSchema,
1222
+ title: z27.string(),
1223
+ inherits_status: z27.boolean(),
1224
+ type: z27.literal("Document"),
1225
+ url: z27.string().url(),
1226
+ app_url: z27.string().url(),
1227
+ bookmark_url: z27.string().url(),
1228
+ subscription_url: z27.string().url(),
1229
+ comments_count: z27.number().int().nonnegative(),
1230
+ comments_url: z27.string().url(),
1231
+ position: z27.number().int().nonnegative(),
1232
+ parent: RecordingRefSchema,
1233
+ bucket: BucketRefSchema,
1234
+ creator: PersonSummarySchema
1235
+ });
1236
+ var DocumentSchema = DocumentCoreSchema.extend({
1237
+ content: HtmlStringSchema
1238
+ });
1239
+ var DocumentListResponseSchema = z27.array(DocumentSchema);
1240
+ var DocumentListQuerySchema = z27.object({
1241
+ page: z27.coerce.number().int().positive().optional()
1242
+ });
1243
+ var DocumentCreateBodySchema = z27.object({
1244
+ title: z27.string().min(1),
1245
+ content: HtmlStringSchema,
1246
+ status: z27.enum(["active", "draft"]).or(z27.string()).optional()
1247
+ });
1248
+ var DocumentUpdateBodySchema = z27.object({
1249
+ title: z27.string().min(1).optional(),
1250
+ content: HtmlStringSchema.optional()
1251
+ }).refine(
1252
+ (value) => Object.keys(value).length > 0,
1253
+ "At least one field must be provided to update a document."
1254
+ );
1255
+
1256
+ // src/contract/schemas/documents/vaults.ts
1257
+ import { z as z28 } from "zod";
1258
+ var VaultCoreSchema = z28.object({
1259
+ id: BasecampIdSchema,
1260
+ status: RecordingStatusSchema,
1261
+ visible_to_clients: z28.boolean(),
1262
+ created_at: IsoDateTimeSchema,
1263
+ updated_at: IsoDateTimeSchema,
1264
+ title: z28.string(),
1265
+ inherits_status: z28.boolean(),
1266
+ type: z28.literal("Vault"),
1267
+ url: z28.string().url(),
1268
+ app_url: z28.string().url(),
1269
+ bookmark_url: z28.string().url(),
1270
+ position: z28.number().int().nonnegative(),
1271
+ parent: RecordingRefSchema.optional(),
1272
+ bucket: BucketRefSchema,
1273
+ creator: PersonSummarySchema
1274
+ });
1275
+ var VaultSchema = VaultCoreSchema.extend({
1276
+ documents_count: z28.number().int().nonnegative(),
1277
+ documents_url: z28.string().url(),
1278
+ uploads_count: z28.number().int().nonnegative(),
1279
+ uploads_url: z28.string().url(),
1280
+ vaults_count: z28.number().int().nonnegative(),
1281
+ vaults_url: z28.string().url()
1282
+ });
1283
+ var VaultListResponseSchema = z28.array(VaultSchema);
1284
+ var VaultListQuerySchema = z28.object({
1285
+ page: z28.coerce.number().int().positive().optional()
1286
+ });
1287
+ var VaultCreateBodySchema = z28.object({
1288
+ title: z28.string().min(1)
1289
+ });
1290
+ var VaultUpdateBodySchema = z28.object({
1291
+ title: z28.string().min(1)
1292
+ });
1293
+
1294
+ // src/contract/schemas/documents/uploads.ts
1295
+ import { z as z29 } from "zod";
1296
+ var UploadCoreSchema = z29.object({
1297
+ id: BasecampIdSchema,
1298
+ status: RecordingStatusSchema,
1299
+ visible_to_clients: z29.boolean(),
1300
+ created_at: IsoDateTimeSchema,
1301
+ updated_at: IsoDateTimeSchema,
1302
+ title: z29.string(),
1303
+ inherits_status: z29.boolean(),
1304
+ type: z29.literal("Upload"),
1305
+ url: z29.string().url(),
1306
+ app_url: z29.string().url(),
1307
+ bookmark_url: z29.string().url(),
1308
+ subscription_url: z29.string().url(),
1309
+ comments_count: z29.number().int().nonnegative(),
1310
+ comments_url: z29.string().url(),
1311
+ position: z29.number().int().nonnegative(),
1312
+ parent: RecordingRefSchema,
1313
+ bucket: BucketRefSchema,
1314
+ creator: PersonSummarySchema
1315
+ });
1316
+ var UploadSchema = UploadCoreSchema.extend({
1317
+ description: HtmlStringSchema.optional(),
1318
+ content_type: z29.string(),
1319
+ byte_size: z29.number().int().nonnegative(),
1320
+ filename: z29.string(),
1321
+ download_url: z29.string().url(),
1322
+ app_download_url: z29.string().url(),
1323
+ width: z29.number().int().nonnegative().optional(),
1324
+ height: z29.number().int().nonnegative().optional()
1325
+ });
1326
+ var UploadListResponseSchema = z29.array(UploadSchema);
1327
+ var UploadListQuerySchema = z29.object({
1328
+ page: z29.coerce.number().int().positive().optional()
1329
+ });
1330
+ var UploadCreateBodySchema = z29.object({
1331
+ attachable_sgid: z29.string().min(1),
1332
+ description: HtmlStringSchema.optional(),
1333
+ base_name: z29.string().optional()
1334
+ });
1335
+ var UploadUpdateBodySchema = z29.object({
1336
+ description: HtmlStringSchema.optional(),
1337
+ base_name: z29.string().optional()
1338
+ }).refine(
1339
+ (value) => Object.keys(value).length > 0,
1340
+ "At least one field must be provided to update an upload."
1341
+ );
1342
+
1343
+ // src/contract/schemas/documents/attachments.ts
1344
+ import { z as z30 } from "zod";
1345
+ var AttachmentResponseSchema = z30.object({
1346
+ attachable_sgid: z30.string().min(1)
1347
+ });
1348
+ var AttachmentCreateQuerySchema = z30.object({
1349
+ name: z30.string().min(1)
1350
+ });
1351
+
1352
+ // src/contract/resources/documents/documents.ts
1353
+ var bucketAndVaultPathParams = z31.object({
1354
+ bucketId: BasecampIdParamSchema,
1355
+ vaultId: BasecampIdParamSchema
1356
+ });
1357
+ var bucketAndDocumentPathParams = z31.object({
1358
+ bucketId: BasecampIdParamSchema,
1359
+ documentId: BasecampIdParamSchema
1360
+ });
1361
+ var documentsRouter = c.router({
1362
+ list: {
1363
+ summary: "List documents",
1364
+ description: "Returns a paginated list of active documents in a vault. Pagination data is available via the Link and X-Total-Count headers.",
1365
+ metadata: {
1366
+ tag: "Documents",
1367
+ operationId: "documents.list",
1368
+ docsPath: "/docs/basecamp-api-specs/sections/documents.md#get-documents"
1369
+ },
1370
+ method: "GET",
1371
+ path: "/buckets/:bucketId/vaults/:vaultId/documents",
1372
+ pathParams: bucketAndVaultPathParams,
1373
+ query: DocumentListQuerySchema,
1374
+ responses: {
1375
+ 200: DocumentListResponseSchema
1376
+ }
1377
+ },
1378
+ get: {
1379
+ summary: "Get a document",
1380
+ description: "Fetch the full representation of a single document.",
1381
+ metadata: {
1382
+ tag: "Documents",
1383
+ operationId: "documents.get",
1384
+ docsPath: "/docs/basecamp-api-specs/sections/documents.md#get-a-document"
1385
+ },
1386
+ method: "GET",
1387
+ path: "/buckets/:bucketId/documents/:documentId",
1388
+ pathParams: bucketAndDocumentPathParams,
1389
+ responses: {
1390
+ 200: DocumentSchema
1391
+ }
1392
+ },
1393
+ create: {
1394
+ summary: "Create a document",
1395
+ description: 'Publish a document in a vault. Setting status to "active" makes the document visible immediately.',
1396
+ metadata: {
1397
+ tag: "Documents",
1398
+ operationId: "documents.create",
1399
+ docsPath: "/docs/basecamp-api-specs/sections/documents.md#create-a-document"
1400
+ },
1401
+ method: "POST",
1402
+ path: "/buckets/:bucketId/vaults/:vaultId/documents",
1403
+ pathParams: bucketAndVaultPathParams,
1404
+ body: DocumentCreateBodySchema,
1405
+ responses: {
1406
+ 201: DocumentSchema
1407
+ }
1408
+ },
1409
+ update: {
1410
+ summary: "Update a document",
1411
+ description: "Update the title or content of an existing document.",
1412
+ metadata: {
1413
+ tag: "Documents",
1414
+ operationId: "documents.update",
1415
+ docsPath: "/docs/basecamp-api-specs/sections/documents.md#update-a-document"
1416
+ },
1417
+ method: "PUT",
1418
+ path: "/buckets/:bucketId/documents/:documentId",
1419
+ pathParams: bucketAndDocumentPathParams,
1420
+ body: DocumentUpdateBodySchema,
1421
+ responses: {
1422
+ 200: DocumentSchema
1423
+ }
1424
+ },
1425
+ trash: {
1426
+ summary: "Trash a document",
1427
+ description: "Move a document recording to the trash. Trashed items can be restored via the UI.",
1428
+ metadata: {
1429
+ tag: "Documents",
1430
+ operationId: "documents.trash",
1431
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
1432
+ },
1433
+ method: "PUT",
1434
+ path: "/buckets/:bucketId/recordings/:documentId/status/trashed",
1435
+ pathParams: bucketAndDocumentPathParams,
1436
+ body: c.noBody(),
1437
+ responses: {
1438
+ 204: c.noBody()
1439
+ }
1440
+ }
1441
+ });
1442
+
1443
+ // src/contract/resources/documents/vaults.ts
1444
+ import { z as z32 } from "zod";
1445
+ var bucketAndVaultPathParams2 = z32.object({
1446
+ bucketId: BasecampIdParamSchema,
1447
+ vaultId: BasecampIdParamSchema
1448
+ });
1449
+ var bucketAndParentVaultPathParams = z32.object({
1450
+ bucketId: BasecampIdParamSchema,
1451
+ parentVaultId: BasecampIdParamSchema
1452
+ });
1453
+ var vaultsRouter = c.router({
1454
+ list: {
1455
+ summary: "List vaults",
1456
+ description: "Returns a paginated list of vaults nested under a parent vault. Pagination data is available via the Link and X-Total-Count headers.",
1457
+ metadata: {
1458
+ tag: "Vaults",
1459
+ operationId: "vaults.list",
1460
+ docsPath: "/docs/basecamp-api-specs/sections/vaults.md#get-vaults"
1461
+ },
1462
+ method: "GET",
1463
+ path: "/buckets/:bucketId/vaults/:parentVaultId/vaults",
1464
+ pathParams: bucketAndParentVaultPathParams,
1465
+ query: VaultListQuerySchema,
1466
+ responses: {
1467
+ 200: VaultListResponseSchema
1468
+ }
1469
+ },
1470
+ get: {
1471
+ summary: "Get a vault",
1472
+ description: "Fetch the full representation of a single vault.",
1473
+ metadata: {
1474
+ tag: "Vaults",
1475
+ operationId: "vaults.get",
1476
+ docsPath: "/docs/basecamp-api-specs/sections/vaults.md#get-a-vault"
1477
+ },
1478
+ method: "GET",
1479
+ path: "/buckets/:bucketId/vaults/:vaultId",
1480
+ pathParams: bucketAndVaultPathParams2,
1481
+ responses: {
1482
+ 200: VaultSchema
1483
+ }
1484
+ },
1485
+ create: {
1486
+ summary: "Create a vault",
1487
+ description: "Create a new vault nested under a parent vault.",
1488
+ metadata: {
1489
+ tag: "Vaults",
1490
+ operationId: "vaults.create",
1491
+ docsPath: "/docs/basecamp-api-specs/sections/vaults.md#create-a-vault"
1492
+ },
1493
+ method: "POST",
1494
+ path: "/buckets/:bucketId/vaults/:parentVaultId/vaults",
1495
+ pathParams: bucketAndParentVaultPathParams,
1496
+ body: VaultCreateBodySchema,
1497
+ responses: {
1498
+ 201: VaultSchema
1499
+ }
1500
+ },
1501
+ update: {
1502
+ summary: "Update a vault",
1503
+ description: "Update the title of an existing vault.",
1504
+ metadata: {
1505
+ tag: "Vaults",
1506
+ operationId: "vaults.update",
1507
+ docsPath: "/docs/basecamp-api-specs/sections/vaults.md#update-a-vault"
1508
+ },
1509
+ method: "PUT",
1510
+ path: "/buckets/:bucketId/vaults/:vaultId",
1511
+ pathParams: bucketAndVaultPathParams2,
1512
+ body: VaultUpdateBodySchema,
1513
+ responses: {
1514
+ 200: VaultSchema
1515
+ }
1516
+ },
1517
+ trash: {
1518
+ summary: "Trash a vault",
1519
+ description: "Move a vault recording to the trash. Trashed items can be restored via the UI.",
1520
+ metadata: {
1521
+ tag: "Vaults",
1522
+ operationId: "vaults.trash",
1523
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
1524
+ },
1525
+ method: "PUT",
1526
+ path: "/buckets/:bucketId/recordings/:vaultId/status/trashed",
1527
+ pathParams: bucketAndVaultPathParams2,
1528
+ body: c.noBody(),
1529
+ responses: {
1530
+ 204: c.noBody()
1531
+ }
1532
+ }
1533
+ });
1534
+
1535
+ // src/contract/resources/documents/uploads.ts
1536
+ import { z as z33 } from "zod";
1537
+ var bucketAndVaultPathParams3 = z33.object({
1538
+ bucketId: BasecampIdParamSchema,
1539
+ vaultId: BasecampIdParamSchema
1540
+ });
1541
+ var bucketAndUploadPathParams = z33.object({
1542
+ bucketId: BasecampIdParamSchema,
1543
+ uploadId: BasecampIdParamSchema
1544
+ });
1545
+ var uploadsRouter = c.router({
1546
+ list: {
1547
+ summary: "List uploads",
1548
+ description: "Returns a paginated list of active uploads in a vault. Pagination data is available via the Link and X-Total-Count headers.",
1549
+ metadata: {
1550
+ tag: "Uploads",
1551
+ operationId: "uploads.list",
1552
+ docsPath: "/docs/basecamp-api-specs/sections/uploads.md#get-uploads"
1553
+ },
1554
+ method: "GET",
1555
+ path: "/buckets/:bucketId/vaults/:vaultId/uploads",
1556
+ pathParams: bucketAndVaultPathParams3,
1557
+ query: UploadListQuerySchema,
1558
+ responses: {
1559
+ 200: UploadListResponseSchema
1560
+ }
1561
+ },
1562
+ get: {
1563
+ summary: "Get an upload",
1564
+ description: "Fetch the full representation of a single upload.",
1565
+ metadata: {
1566
+ tag: "Uploads",
1567
+ operationId: "uploads.get",
1568
+ docsPath: "/docs/basecamp-api-specs/sections/uploads.md#get-an-upload"
1569
+ },
1570
+ method: "GET",
1571
+ path: "/buckets/:bucketId/uploads/:uploadId",
1572
+ pathParams: bucketAndUploadPathParams,
1573
+ responses: {
1574
+ 200: UploadSchema
1575
+ }
1576
+ },
1577
+ create: {
1578
+ summary: "Create an upload",
1579
+ description: "Create an upload in a vault using a previously obtained attachable_sgid from the attachments endpoint.",
1580
+ metadata: {
1581
+ tag: "Uploads",
1582
+ operationId: "uploads.create",
1583
+ docsPath: "/docs/basecamp-api-specs/sections/uploads.md#create-an-upload"
1584
+ },
1585
+ method: "POST",
1586
+ path: "/buckets/:bucketId/vaults/:vaultId/uploads",
1587
+ pathParams: bucketAndVaultPathParams3,
1588
+ body: UploadCreateBodySchema,
1589
+ responses: {
1590
+ 201: UploadSchema
1591
+ }
1592
+ },
1593
+ update: {
1594
+ summary: "Update an upload",
1595
+ description: "Update the description or base name of an existing upload.",
1596
+ metadata: {
1597
+ tag: "Uploads",
1598
+ operationId: "uploads.update",
1599
+ docsPath: "/docs/basecamp-api-specs/sections/uploads.md#update-an-upload"
1600
+ },
1601
+ method: "PUT",
1602
+ path: "/buckets/:bucketId/uploads/:uploadId",
1603
+ pathParams: bucketAndUploadPathParams,
1604
+ body: UploadUpdateBodySchema,
1605
+ responses: {
1606
+ 200: UploadSchema
1607
+ }
1608
+ },
1609
+ trash: {
1610
+ summary: "Trash an upload",
1611
+ description: "Move an upload recording to the trash. Trashed items can be restored via the UI.",
1612
+ metadata: {
1613
+ tag: "Uploads",
1614
+ operationId: "uploads.trash",
1615
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
1616
+ },
1617
+ method: "PUT",
1618
+ path: "/buckets/:bucketId/recordings/:uploadId/status/trashed",
1619
+ pathParams: bucketAndUploadPathParams,
1620
+ body: c.noBody(),
1621
+ responses: {
1622
+ 204: c.noBody()
1623
+ }
1624
+ }
1625
+ });
1626
+
1627
+ // src/contract/resources/documents/attachments.ts
1628
+ var attachmentsRouter = c.router({
1629
+ create: {
1630
+ summary: "Create an attachment",
1631
+ description: "Upload a file to get an attachable_sgid that can be used in subsequent requests to create uploads or documents. The request body should be the raw binary file data. Note: Content-Type and Content-Length headers must be set by the caller.",
1632
+ metadata: {
1633
+ tag: "Attachments",
1634
+ operationId: "attachments.create",
1635
+ docsPath: "/docs/basecamp-api-specs/sections/attachments.md#create-an-attachment"
1636
+ },
1637
+ method: "POST",
1638
+ path: "/attachments",
1639
+ query: AttachmentCreateQuerySchema,
1640
+ body: c.type(),
1641
+ responses: {
1642
+ 201: AttachmentResponseSchema
1643
+ }
1644
+ }
1645
+ });
1646
+
1647
+ // src/contract/resources/events.ts
1648
+ import { z as z35 } from "zod";
1649
+
1650
+ // src/contract/schemas/events.ts
1651
+ import { z as z34 } from "zod";
1652
+ var EventDetailsSchema = z34.object({}).passthrough();
1653
+ var RecordingEventSchema = z34.object({
1654
+ id: BasecampIdSchema,
1655
+ recording_id: BasecampIdSchema,
1656
+ action: z34.string(),
1657
+ details: EventDetailsSchema,
1658
+ created_at: IsoDateTimeSchema,
1659
+ creator: PersonSummarySchema
1660
+ });
1661
+ var RecordingEventListResponseSchema = z34.array(RecordingEventSchema);
1662
+ var RecordingEventListQuerySchema = z34.object({
1663
+ page: z34.coerce.number().int().positive().optional()
1664
+ });
1665
+
1666
+ // src/contract/resources/events.ts
1667
+ var RecordingEventsPathParamsSchema = z35.object({
1668
+ bucketId: BasecampIdParamSchema,
1669
+ recordingId: BasecampIdParamSchema
1670
+ });
1671
+ var eventsRouter = c.router({
1672
+ listForRecording: {
1673
+ summary: "List recording events",
1674
+ description: "Returns the event history for a specific recording. Pagination data is available via Link headers.",
1675
+ metadata: {
1676
+ tag: "Events",
1677
+ operationId: "events.listForRecording",
1678
+ docsPath: "/docs/basecamp-api-specs/sections/events.md#get-events"
1679
+ },
1680
+ method: "GET",
1681
+ path: "/buckets/:bucketId/recordings/:recordingId/events",
1682
+ pathParams: RecordingEventsPathParamsSchema,
1683
+ query: RecordingEventListQuerySchema.optional(),
1684
+ responses: {
1685
+ 200: RecordingEventListResponseSchema
1686
+ }
1687
+ }
1688
+ });
1689
+
1690
+ // src/contract/resources/lineup-markers.ts
1691
+ import { z as z37 } from "zod";
1692
+
1693
+ // src/contract/schemas/lineup-markers.ts
1694
+ import { z as z36 } from "zod";
1695
+ var LineupMarkerCreateBodySchema = z36.object({
1696
+ name: z36.string().min(1),
1697
+ date: IsoDateSchema
1698
+ });
1699
+ var LineupMarkerUpdateBodySchema = z36.object({
1700
+ name: z36.string().min(1).optional(),
1701
+ date: IsoDateSchema.optional()
1702
+ }).refine((value) => value.name !== void 0 || value.date !== void 0, {
1703
+ message: "Either name or date must be provided."
1704
+ });
1705
+
1706
+ // src/contract/resources/lineup-markers.ts
1707
+ var LineupMarkerPathParamsSchema = z37.object({
1708
+ markerId: BasecampIdParamSchema
1709
+ });
1710
+ var lineupMarkersRouter = c.router({
1711
+ create: {
1712
+ summary: "Create a lineup marker",
1713
+ description: "Create an account-wide lineup marker that appears on the Lineup timeline.",
1714
+ metadata: {
1715
+ tag: "LineupMarkers",
1716
+ operationId: "lineupMarkers.create",
1717
+ docsPath: "/docs/basecamp-api-specs/sections/lineup_markers.md#create-a-marker"
1718
+ },
1719
+ method: "POST",
1720
+ path: "/lineup/markers",
1721
+ body: LineupMarkerCreateBodySchema,
1722
+ responses: {
1723
+ 201: c.noBody()
1724
+ }
1725
+ },
1726
+ update: {
1727
+ summary: "Update a lineup marker",
1728
+ description: "Update the name or date of an existing lineup marker.",
1729
+ metadata: {
1730
+ tag: "LineupMarkers",
1731
+ operationId: "lineupMarkers.update",
1732
+ docsPath: "/docs/basecamp-api-specs/sections/lineup_markers.md#update-a-marker"
1733
+ },
1734
+ method: "PUT",
1735
+ path: "/lineup/markers/:markerId",
1736
+ pathParams: LineupMarkerPathParamsSchema,
1737
+ body: LineupMarkerUpdateBodySchema,
1738
+ responses: {
1739
+ 200: c.noBody()
1740
+ }
1741
+ },
1742
+ destroy: {
1743
+ summary: "Destroy a lineup marker",
1744
+ description: "Permanently delete a lineup marker immediately.",
1745
+ metadata: {
1746
+ tag: "LineupMarkers",
1747
+ operationId: "lineupMarkers.destroy",
1748
+ docsPath: "/docs/basecamp-api-specs/sections/lineup_markers.md#destroy-a-marker"
1749
+ },
1750
+ method: "DELETE",
1751
+ path: "/lineup/markers/:markerId",
1752
+ pathParams: LineupMarkerPathParamsSchema,
1753
+ body: c.noBody(),
1754
+ responses: {
1755
+ 204: c.noBody()
1756
+ }
1757
+ }
1758
+ });
1759
+
1760
+ // src/contract/resources/people.ts
1761
+ import { z as z39 } from "zod";
1762
+
1763
+ // src/contract/schemas/people.ts
1764
+ import { z as z38 } from "zod";
1765
+ var PersonSchema = PersonSummarySchema;
1766
+ var PeopleListQuerySchema = z38.object({
1767
+ page: z38.coerce.number().int().positive().optional()
1768
+ });
1769
+ var PeopleListResponseSchema = z38.array(PersonSchema);
1770
+ var ProjectAccessCreateEntrySchema = z38.object({
1771
+ name: z38.string().min(1),
1772
+ email_address: z38.string().email(),
1773
+ title: z38.string().optional(),
1774
+ company_name: z38.string().optional()
1775
+ });
1776
+ var ProjectPeopleAccessBodySchema = z38.object({
1777
+ grant: z38.array(BasecampIdSchema).min(1).optional(),
1778
+ revoke: z38.array(BasecampIdSchema).min(1).optional(),
1779
+ create: z38.array(ProjectAccessCreateEntrySchema).min(1).optional()
1780
+ }).refine(
1781
+ (value) => value.grant !== void 0 || value.revoke !== void 0 || value.create !== void 0,
1782
+ {
1783
+ message: "At least one of grant, revoke, or create must be provided.",
1784
+ path: ["grant"]
1785
+ }
1786
+ );
1787
+ var ProjectPeopleAccessResponseSchema = z38.object({
1788
+ granted: z38.array(PersonSchema),
1789
+ revoked: z38.array(PersonSchema)
1790
+ });
1791
+
1792
+ // src/contract/resources/people.ts
1793
+ var ProjectPathParamsSchema = z39.object({
1794
+ projectId: BasecampIdParamSchema
1795
+ });
1796
+ var PersonPathParamsSchema = z39.object({
1797
+ personId: BasecampIdParamSchema
1798
+ });
1799
+ var peopleRouter = c.router({
1800
+ list: {
1801
+ summary: "List people",
1802
+ description: "Returns the people visible to the authenticated user across the entire Basecamp account. Pagination data is provided through Link headers when the dataset exceeds a single page.",
1803
+ metadata: {
1804
+ tag: "People",
1805
+ operationId: "people.list",
1806
+ docsPath: "/docs/basecamp-api-specs/sections/people.md#get-all-people"
1807
+ },
1808
+ method: "GET",
1809
+ path: "/people",
1810
+ query: PeopleListQuerySchema.optional(),
1811
+ responses: {
1812
+ 200: PeopleListResponseSchema
1813
+ }
1814
+ },
1815
+ listForProject: {
1816
+ summary: "List project people",
1817
+ description: "Returns the active people on a specific project.",
1818
+ metadata: {
1819
+ tag: "People",
1820
+ operationId: "people.listForProject",
1821
+ docsPath: "/docs/basecamp-api-specs/sections/people.md#get-people-on-a-project"
1822
+ },
1823
+ method: "GET",
1824
+ path: "/projects/:projectId/people",
1825
+ pathParams: ProjectPathParamsSchema,
1826
+ responses: {
1827
+ 200: PeopleListResponseSchema
1828
+ }
1829
+ },
1830
+ updateProjectAccess: {
1831
+ summary: "Update project access",
1832
+ description: "Grant, revoke, or create people directly on a project. At least one of grant, revoke, or create must be present in the request body.",
1833
+ metadata: {
1834
+ tag: "People",
1835
+ operationId: "people.updateProjectAccess",
1836
+ docsPath: "/docs/basecamp-api-specs/sections/people.md#update-who-can-access-a-project"
1837
+ },
1838
+ method: "PUT",
1839
+ path: "/projects/:projectId/people/users",
1840
+ pathParams: ProjectPathParamsSchema,
1841
+ body: ProjectPeopleAccessBodySchema,
1842
+ responses: {
1843
+ 200: ProjectPeopleAccessResponseSchema
1844
+ }
1845
+ },
1846
+ listPingable: {
1847
+ summary: "List pingable people",
1848
+ description: "Returns the people who can be pinged by the authenticated user. The endpoint is not paginated.",
1849
+ metadata: {
1850
+ tag: "People",
1851
+ operationId: "people.listPingable",
1852
+ docsPath: "/docs/basecamp-api-specs/sections/people.md#get-pingable-people"
1853
+ },
1854
+ method: "GET",
1855
+ path: "/circles/people",
1856
+ responses: {
1857
+ 200: PeopleListResponseSchema
1858
+ }
1859
+ },
1860
+ get: {
1861
+ summary: "Get a person",
1862
+ description: "Fetch the profile for a person by identifier.",
1863
+ metadata: {
1864
+ tag: "People",
1865
+ operationId: "people.get",
1866
+ docsPath: "/docs/basecamp-api-specs/sections/people.md#get-person"
1867
+ },
1868
+ method: "GET",
1869
+ path: "/people/:personId",
1870
+ pathParams: PersonPathParamsSchema,
1871
+ responses: {
1872
+ 200: PersonSchema
1873
+ }
1874
+ },
1875
+ me: {
1876
+ summary: "Get my personal info",
1877
+ description: "Fetch the profile for the authenticated user.",
1878
+ metadata: {
1879
+ tag: "People",
1880
+ operationId: "people.me",
1881
+ docsPath: "/docs/basecamp-api-specs/sections/people.md#get-my-personal-info"
1882
+ },
1883
+ method: "GET",
1884
+ path: "/my/profile",
1885
+ responses: {
1886
+ 200: PersonSchema
1887
+ }
1888
+ }
1889
+ });
1890
+
1891
+ // src/contract/resources/projects.ts
1892
+ import { z as z41 } from "zod";
1893
+
1894
+ // src/contract/schemas/projects.ts
1895
+ import { z as z40 } from "zod";
1896
+ var ProjectDockEntrySchema = z40.object({
1897
+ id: BasecampIdSchema,
1898
+ title: z40.string(),
1899
+ name: z40.string(),
1900
+ enabled: z40.boolean(),
1901
+ position: z40.number().int().nullable(),
1902
+ url: z40.string().url(),
1903
+ app_url: z40.string().url()
1904
+ });
1905
+ var ProjectClientCompanySchema = z40.object({
1906
+ id: BasecampIdSchema,
1907
+ name: z40.string()
1908
+ });
1909
+ var ProjectClientsideSchema = z40.object({
1910
+ url: z40.string().url(),
1911
+ app_url: z40.string().url()
1912
+ });
1913
+ var ProjectStatusSchema = z40.enum(["active", "archived", "trashed"]).or(z40.string());
1914
+ var ProjectCoreSchema = z40.object({
1915
+ id: BasecampIdSchema,
1916
+ status: ProjectStatusSchema,
1917
+ created_at: IsoDateTimeSchema,
1918
+ updated_at: IsoDateTimeSchema,
1919
+ name: z40.string(),
1920
+ description: HtmlStringSchema.nullable().optional(),
1921
+ purpose: z40.string(),
1922
+ clients_enabled: z40.boolean(),
1923
+ bookmark_url: z40.string().url(),
1924
+ url: z40.string().url(),
1925
+ app_url: z40.string().url(),
1926
+ dock: z40.array(ProjectDockEntrySchema),
1927
+ client_company: ProjectClientCompanySchema.optional(),
1928
+ clientside: ProjectClientsideSchema.optional()
1929
+ });
1930
+ var ProjectSchema = ProjectCoreSchema.extend({
1931
+ bookmarked: z40.boolean().optional()
1932
+ });
1933
+ var ProjectListResponseSchema = z40.array(ProjectSchema);
1934
+ var ProjectListQuerySchema = z40.object({
1935
+ status: z40.enum(["active", "archived", "trashed"]).or(z40.string()).optional(),
1936
+ page: z40.coerce.number().int().positive().optional()
1937
+ });
1938
+ var ProjectCreateBodySchema = z40.object({
1939
+ name: z40.string().min(1),
1940
+ description: HtmlStringSchema.nullable().optional()
1941
+ });
1942
+ var ScheduleAttributesSchema = z40.object({
1943
+ start_date: z40.string().date().optional(),
1944
+ end_date: z40.string().date().optional()
1945
+ }).refine(
1946
+ (value) => value.start_date === void 0 && value.end_date === void 0 || value.start_date !== void 0 && value.end_date !== void 0,
1947
+ {
1948
+ message: "Both start_date and end_date must be provided together.",
1949
+ path: ["end_date"]
1950
+ }
1951
+ );
1952
+ var ProjectUpdateBodySchema = z40.object({
1953
+ name: z40.string().min(1),
1954
+ description: HtmlStringSchema.nullable().optional(),
1955
+ admissions: z40.enum(["invite", "employee", "team"]).or(z40.string()).optional(),
1956
+ schedule_attributes: ScheduleAttributesSchema.optional()
1957
+ });
1958
+
1959
+ // src/contract/resources/projects.ts
1960
+ var ProjectPathParamsSchema2 = z41.object({
1961
+ projectId: BasecampIdParamSchema
1962
+ });
1963
+ var projectsRouter = c.router({
1964
+ list: {
1965
+ summary: "List projects",
1966
+ description: "Returns active projects visible to the authenticated user. Pagination data is exposed via standard Link headers.",
1967
+ metadata: {
1968
+ tag: "Projects",
1969
+ operationId: "projects.list",
1970
+ docsPath: "/docs/basecamp-api-specs/sections/projects.md#get-projects"
1971
+ },
1972
+ method: "GET",
1973
+ path: "/projects",
1974
+ query: ProjectListQuerySchema.optional(),
1975
+ responses: {
1976
+ 200: ProjectListResponseSchema
1977
+ }
1978
+ },
1979
+ get: {
1980
+ summary: "Get a project",
1981
+ description: "Fetch the full representation of a single project by its identifier.",
1982
+ metadata: {
1983
+ tag: "Projects",
1984
+ operationId: "projects.get",
1985
+ docsPath: "/docs/basecamp-api-specs/sections/projects.md#get-a-project"
1986
+ },
1987
+ method: "GET",
1988
+ path: "/projects/:projectId",
1989
+ pathParams: ProjectPathParamsSchema2,
1990
+ responses: {
1991
+ 200: ProjectSchema
1992
+ }
1993
+ },
1994
+ create: {
1995
+ summary: "Create a project",
1996
+ description: "Create a new project with an optional description.",
1997
+ metadata: {
1998
+ tag: "Projects",
1999
+ operationId: "projects.create",
2000
+ docsPath: "/docs/basecamp-api-specs/sections/projects.md#create-a-project"
2001
+ },
2002
+ method: "POST",
2003
+ path: "/projects",
2004
+ body: ProjectCreateBodySchema,
2005
+ responses: {
2006
+ 201: ProjectSchema,
2007
+ 507: z41.object({
2008
+ error: z41.string()
2009
+ })
2010
+ }
2011
+ },
2012
+ update: {
2013
+ summary: "Update a project",
2014
+ description: "Update a project name, description, admissions policy, or schedule dates. Basecamp requires the name to be present in every update request.",
2015
+ metadata: {
2016
+ tag: "Projects",
2017
+ operationId: "projects.update",
2018
+ docsPath: "/docs/basecamp-api-specs/sections/projects.md#update-a-project"
2019
+ },
2020
+ method: "PUT",
2021
+ path: "/projects/:projectId",
2022
+ pathParams: ProjectPathParamsSchema2,
2023
+ body: ProjectUpdateBodySchema,
2024
+ responses: {
2025
+ 200: ProjectSchema
2026
+ }
2027
+ },
2028
+ trash: {
2029
+ summary: "Trash a project",
2030
+ description: "Move a project to the trash. The project will be permanently deleted after 30 days unless restored via the UI.",
2031
+ metadata: {
2032
+ tag: "Projects",
2033
+ operationId: "projects.trash",
2034
+ docsPath: "/docs/basecamp-api-specs/sections/projects.md#trash-a-project"
2035
+ },
2036
+ method: "DELETE",
2037
+ path: "/projects/:projectId",
2038
+ pathParams: ProjectPathParamsSchema2,
2039
+ body: c.noBody(),
2040
+ responses: {
2041
+ 204: c.noBody()
2042
+ }
2043
+ }
2044
+ });
2045
+
2046
+ // src/contract/resources/recordings.ts
2047
+ import { z as z42 } from "zod";
2048
+ var BucketRecordingPathParamsSchema = z42.object({
2049
+ bucketId: BasecampIdParamSchema,
2050
+ recordingId: BasecampIdParamSchema
2051
+ });
2052
+ var recordingsRouter = c.router({
2053
+ list: {
2054
+ summary: "List recordings",
2055
+ description: "Returns a paginated list of recordings filtered by type and optional bucket or status filters. Use this endpoint to enumerate cross-project activity for a specific recording type.",
2056
+ metadata: {
2057
+ tag: "Recordings",
2058
+ operationId: "recordings.list",
2059
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#get-recordings"
2060
+ },
2061
+ method: "GET",
2062
+ path: "/projects/recordings",
2063
+ query: RecordingListQuerySchema,
2064
+ responses: {
2065
+ 200: RecordingListResponseSchema
2066
+ }
2067
+ },
2068
+ trash: {
2069
+ summary: "Trash a recording",
2070
+ description: "Mark a recording as trashed. Trashed recordings can be restored via the UI.",
2071
+ metadata: {
2072
+ tag: "Recordings",
2073
+ operationId: "recordings.trash",
2074
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
2075
+ },
2076
+ method: "PUT",
2077
+ path: "/buckets/:bucketId/recordings/:recordingId/status/trashed",
2078
+ pathParams: BucketRecordingPathParamsSchema,
2079
+ body: c.noBody(),
2080
+ responses: {
2081
+ 204: c.noBody()
2082
+ }
2083
+ },
2084
+ archive: {
2085
+ summary: "Archive a recording",
2086
+ description: "Mark a recording as archived. Archived recordings remain available but hidden.",
2087
+ metadata: {
2088
+ tag: "Recordings",
2089
+ operationId: "recordings.archive",
2090
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#archive-a-recording"
2091
+ },
2092
+ method: "PUT",
2093
+ path: "/buckets/:bucketId/recordings/:recordingId/status/archived",
2094
+ pathParams: BucketRecordingPathParamsSchema,
2095
+ body: c.noBody(),
2096
+ responses: {
2097
+ 204: c.noBody()
2098
+ }
2099
+ },
2100
+ activate: {
2101
+ summary: "Unarchive a recording",
2102
+ description: "Mark a recording as active to reverse a previous archive action.",
2103
+ metadata: {
2104
+ tag: "Recordings",
2105
+ operationId: "recordings.activate",
2106
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#unarchive-a-recording"
2107
+ },
2108
+ method: "PUT",
2109
+ path: "/buckets/:bucketId/recordings/:recordingId/status/active",
2110
+ pathParams: BucketRecordingPathParamsSchema,
2111
+ body: c.noBody(),
2112
+ responses: {
2113
+ 204: c.noBody()
2114
+ }
2115
+ }
2116
+ });
2117
+
2118
+ // src/contract/resources/scheduling/schedules.ts
2119
+ import { z as z44 } from "zod";
2120
+
2121
+ // src/contract/schemas/scheduling/schedules.ts
2122
+ import { z as z43 } from "zod";
2123
+ var ScheduleSchema = z43.object({
2124
+ id: BasecampIdSchema,
2125
+ status: RecordingStatusSchema,
2126
+ visible_to_clients: z43.boolean(),
2127
+ created_at: IsoDateTimeSchema,
2128
+ updated_at: IsoDateTimeSchema,
2129
+ title: z43.string(),
2130
+ inherits_status: z43.boolean(),
2131
+ type: z43.literal("Schedule"),
2132
+ url: z43.string().url(),
2133
+ app_url: z43.string().url(),
2134
+ bookmark_url: z43.string().url(),
2135
+ position: z43.number().int(),
2136
+ bucket: BucketRefSchema,
2137
+ creator: PersonSummarySchema,
2138
+ include_due_assignments: z43.boolean(),
2139
+ entries_count: z43.number().int(),
2140
+ entries_url: z43.string().url()
2141
+ });
2142
+ var ScheduleUpdateBodySchema = z43.object({
2143
+ include_due_assignments: z43.boolean()
2144
+ });
2145
+
2146
+ // src/contract/resources/scheduling/schedules.ts
2147
+ var bucketAndSchedulePathParams = z44.object({
2148
+ bucketId: BasecampIdParamSchema,
2149
+ scheduleId: BasecampIdParamSchema
2150
+ });
2151
+ var schedulesRouter = c.router({
2152
+ get: {
2153
+ summary: "Get schedule",
2154
+ description: "Returns the schedule for a project. All schedule entries under a project are children of this resource.",
2155
+ metadata: {
2156
+ tag: "Schedules",
2157
+ operationId: "schedules.get",
2158
+ docsPath: "/docs/basecamp-api-specs/sections/schedules.md#get-schedule"
2159
+ },
2160
+ method: "GET",
2161
+ path: "/buckets/:bucketId/schedules/:scheduleId",
2162
+ pathParams: bucketAndSchedulePathParams,
2163
+ responses: {
2164
+ 200: ScheduleSchema
2165
+ }
2166
+ },
2167
+ update: {
2168
+ summary: "Update a schedule",
2169
+ description: "Update whether the schedule should include due dates from to-dos, cards, and steps.",
2170
+ metadata: {
2171
+ tag: "Schedules",
2172
+ operationId: "schedules.update",
2173
+ docsPath: "/docs/basecamp-api-specs/sections/schedules.md#update-a-schedule"
2174
+ },
2175
+ method: "PUT",
2176
+ path: "/buckets/:bucketId/schedules/:scheduleId",
2177
+ pathParams: bucketAndSchedulePathParams,
2178
+ body: ScheduleUpdateBodySchema,
2179
+ responses: {
2180
+ 200: ScheduleSchema
2181
+ }
2182
+ }
2183
+ });
2184
+
2185
+ // src/contract/resources/scheduling/schedule-entries.ts
2186
+ import { z as z46 } from "zod";
2187
+
2188
+ // src/contract/schemas/scheduling/schedule-entries.ts
2189
+ import { z as z45 } from "zod";
2190
+ var RecurrenceScheduleSchema = z45.object({
2191
+ frequency: z45.string(),
2192
+ days: z45.array(z45.number().int()),
2193
+ hour: z45.number().int(),
2194
+ minute: z45.number().int(),
2195
+ week_instance: z45.number().int().nullable(),
2196
+ week_interval: z45.number().int().nullable(),
2197
+ month_interval: z45.number().int().nullable(),
2198
+ start_date: z45.string(),
2199
+ end_date: z45.string().nullable()
2200
+ });
2201
+ var ScheduleEntrySchema = z45.object({
2202
+ id: BasecampIdSchema,
2203
+ status: RecordingStatusSchema,
2204
+ visible_to_clients: z45.boolean(),
2205
+ created_at: IsoDateTimeSchema,
2206
+ updated_at: IsoDateTimeSchema,
2207
+ title: z45.string(),
2208
+ inherits_status: z45.boolean(),
2209
+ type: z45.literal("Schedule::Entry"),
2210
+ url: z45.string().url(),
2211
+ app_url: z45.string().url(),
2212
+ bookmark_url: z45.string().url(),
2213
+ subscription_url: z45.string().url(),
2214
+ comments_count: z45.number().int(),
2215
+ comments_url: z45.string().url(),
2216
+ parent: RecordingRefSchema,
2217
+ bucket: BucketRefSchema,
2218
+ creator: PersonSummarySchema,
2219
+ description: HtmlStringSchema,
2220
+ summary: z45.string(),
2221
+ all_day: z45.boolean(),
2222
+ starts_at: z45.string(),
2223
+ ends_at: z45.string(),
2224
+ participants: z45.array(PersonSummarySchema),
2225
+ recurrence_schedule: RecurrenceScheduleSchema.optional()
2226
+ });
2227
+ var ScheduleEntryListResponseSchema = z45.array(ScheduleEntrySchema);
2228
+ var ScheduleEntryListQuerySchema = z45.object({
2229
+ status: RecordingStatusSchema.optional(),
2230
+ page: z45.coerce.number().int().positive().optional()
2231
+ });
2232
+ var ScheduleEntryCreateBodySchema = z45.object({
2233
+ summary: z45.string(),
2234
+ starts_at: z45.string(),
2235
+ ends_at: z45.string(),
2236
+ description: HtmlStringSchema.optional(),
2237
+ participant_ids: z45.array(BasecampIdSchema).optional(),
2238
+ all_day: z45.boolean().optional(),
2239
+ notify: z45.boolean().optional()
2240
+ });
2241
+ var ScheduleEntryUpdateBodySchema = z45.object({
2242
+ summary: z45.string().optional(),
2243
+ starts_at: z45.string().optional(),
2244
+ ends_at: z45.string().optional(),
2245
+ description: HtmlStringSchema.optional(),
2246
+ participant_ids: z45.array(BasecampIdSchema).optional(),
2247
+ all_day: z45.boolean().optional(),
2248
+ notify: z45.boolean().optional()
2249
+ });
2250
+
2251
+ // src/contract/resources/scheduling/schedule-entries.ts
2252
+ var bucketAndSchedulePathParams2 = z46.object({
2253
+ bucketId: BasecampIdParamSchema,
2254
+ scheduleId: BasecampIdParamSchema
2255
+ });
2256
+ var bucketAndEntryPathParams = z46.object({
2257
+ bucketId: BasecampIdParamSchema,
2258
+ scheduleEntryId: BasecampIdParamSchema
2259
+ });
2260
+ var bucketEntryOccurrencePathParams = z46.object({
2261
+ bucketId: BasecampIdParamSchema,
2262
+ scheduleEntryId: BasecampIdParamSchema,
2263
+ occurrenceDate: z46.string()
2264
+ });
2265
+ var scheduleEntriesRouter = c.router({
2266
+ list: {
2267
+ summary: "List schedule entries",
2268
+ description: "Returns a paginated list of schedule entries in a schedule. Use status filter to get archived or trashed entries.",
2269
+ metadata: {
2270
+ tag: "Schedule Entries",
2271
+ operationId: "scheduleEntries.list",
2272
+ docsPath: "/docs/basecamp-api-specs/sections/schedule_entries.md#get-schedule-entries"
2273
+ },
2274
+ method: "GET",
2275
+ path: "/buckets/:bucketId/schedules/:scheduleId/entries",
2276
+ pathParams: bucketAndSchedulePathParams2,
2277
+ query: ScheduleEntryListQuerySchema,
2278
+ responses: {
2279
+ 200: ScheduleEntryListResponseSchema
2280
+ }
2281
+ },
2282
+ get: {
2283
+ summary: "Get a schedule entry",
2284
+ description: "Returns a schedule entry. For recurring entries, this redirects to the first occurrence.",
2285
+ metadata: {
2286
+ tag: "Schedule Entries",
2287
+ operationId: "scheduleEntries.get",
2288
+ docsPath: "/docs/basecamp-api-specs/sections/schedule_entries.md#get-a-schedule-entry"
2289
+ },
2290
+ method: "GET",
2291
+ path: "/buckets/:bucketId/schedule_entries/:scheduleEntryId",
2292
+ pathParams: bucketAndEntryPathParams,
2293
+ responses: {
2294
+ 200: ScheduleEntrySchema
2295
+ }
2296
+ },
2297
+ getOccurrence: {
2298
+ summary: "Get a specific occurrence of a recurring schedule entry",
2299
+ description: "Returns a specific occurrence of a recurring schedule entry (e.g., 20190218 for February 18, 2019).",
2300
+ metadata: {
2301
+ tag: "Schedule Entries",
2302
+ operationId: "scheduleEntries.getOccurrence",
2303
+ docsPath: "/docs/basecamp-api-specs/sections/schedule_entries.md#get-a-schedule-entry"
2304
+ },
2305
+ method: "GET",
2306
+ path: "/buckets/:bucketId/schedule_entries/:scheduleEntryId/occurrences/:occurrenceDate",
2307
+ pathParams: bucketEntryOccurrencePathParams,
2308
+ responses: {
2309
+ 200: ScheduleEntrySchema
2310
+ }
2311
+ },
2312
+ create: {
2313
+ summary: "Create a schedule entry",
2314
+ description: "Creates a new schedule entry in a schedule. Required fields: summary, starts_at, and ends_at.",
2315
+ metadata: {
2316
+ tag: "Schedule Entries",
2317
+ operationId: "scheduleEntries.create",
2318
+ docsPath: "/docs/basecamp-api-specs/sections/schedule_entries.md#create-a-schedule-entry"
2319
+ },
2320
+ method: "POST",
2321
+ path: "/buckets/:bucketId/schedules/:scheduleId/entries",
2322
+ pathParams: bucketAndSchedulePathParams2,
2323
+ body: ScheduleEntryCreateBodySchema,
2324
+ responses: {
2325
+ 201: ScheduleEntrySchema
2326
+ }
2327
+ },
2328
+ update: {
2329
+ summary: "Update a schedule entry",
2330
+ description: "Updates an existing schedule entry. Any create parameters can be changed.",
2331
+ metadata: {
2332
+ tag: "Schedule Entries",
2333
+ operationId: "scheduleEntries.update",
2334
+ docsPath: "/docs/basecamp-api-specs/sections/schedule_entries.md#update-a-schedule-entry"
2335
+ },
2336
+ method: "PUT",
2337
+ path: "/buckets/:bucketId/schedule_entries/:scheduleEntryId",
2338
+ pathParams: bucketAndEntryPathParams,
2339
+ body: ScheduleEntryUpdateBodySchema,
2340
+ responses: {
2341
+ 200: ScheduleEntrySchema
2342
+ }
2343
+ },
2344
+ trash: {
2345
+ summary: "Trash a schedule entry",
2346
+ description: "Moves a schedule entry to the trash. Trashed items can be restored via the UI.",
2347
+ metadata: {
2348
+ tag: "Schedule Entries",
2349
+ operationId: "scheduleEntries.trash",
2350
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
2351
+ },
2352
+ method: "PUT",
2353
+ path: "/buckets/:bucketId/recordings/:scheduleEntryId/status/trashed",
2354
+ pathParams: bucketAndEntryPathParams,
2355
+ body: c.noBody(),
2356
+ responses: {
2357
+ 204: c.noBody()
2358
+ }
2359
+ }
2360
+ });
2361
+
2362
+ // src/contract/resources/scheduling/questionnaires.ts
2363
+ import { z as z48 } from "zod";
2364
+
2365
+ // src/contract/schemas/scheduling/questionnaires.ts
2366
+ import { z as z47 } from "zod";
2367
+ var QuestionnaireSchema = z47.object({
2368
+ id: BasecampIdSchema,
2369
+ status: RecordingStatusSchema,
2370
+ visible_to_clients: z47.boolean(),
2371
+ created_at: IsoDateTimeSchema,
2372
+ updated_at: IsoDateTimeSchema,
2373
+ title: z47.string(),
2374
+ inherits_status: z47.boolean(),
2375
+ type: z47.literal("Questionnaire"),
2376
+ url: z47.string().url(),
2377
+ app_url: z47.string().url(),
2378
+ bookmark_url: z47.string().url(),
2379
+ bucket: BucketRefSchema,
2380
+ creator: PersonSummarySchema,
2381
+ name: z47.string(),
2382
+ questions_count: z47.number().int(),
2383
+ questions_url: z47.string().url()
2384
+ });
2385
+
2386
+ // src/contract/resources/scheduling/questionnaires.ts
2387
+ var bucketAndQuestionnairePathParams = z48.object({
2388
+ bucketId: BasecampIdParamSchema,
2389
+ questionnaireId: BasecampIdParamSchema
2390
+ });
2391
+ var questionnairesRouter = c.router({
2392
+ get: {
2393
+ summary: "Get questionnaire",
2394
+ description: "Returns the questionnaire for a project. All automatic check-in questions are children of this resource.",
2395
+ metadata: {
2396
+ tag: "Questionnaires",
2397
+ operationId: "questionnaires.get",
2398
+ docsPath: "/docs/basecamp-api-specs/sections/questionnaires.md#get-questionnaire"
2399
+ },
2400
+ method: "GET",
2401
+ path: "/buckets/:bucketId/questionnaires/:questionnaireId",
2402
+ pathParams: bucketAndQuestionnairePathParams,
2403
+ responses: {
2404
+ 200: QuestionnaireSchema
2405
+ }
2406
+ }
2407
+ });
2408
+
2409
+ // src/contract/resources/scheduling/questions.ts
2410
+ import { z as z50 } from "zod";
2411
+
2412
+ // src/contract/schemas/scheduling/questions.ts
2413
+ import { z as z49 } from "zod";
2414
+ var QuestionScheduleSchema = z49.object({
2415
+ frequency: z49.string(),
2416
+ days: z49.array(z49.number().int()),
2417
+ hour: z49.number().int(),
2418
+ minute: z49.number().int(),
2419
+ week_instance: z49.number().int().nullable(),
2420
+ week_interval: z49.number().int().nullable(),
2421
+ month_interval: z49.number().int().nullable(),
2422
+ start_date: z49.string(),
2423
+ end_date: z49.string().nullable()
2424
+ });
2425
+ var QuestionSchema = z49.object({
2426
+ id: BasecampIdSchema,
2427
+ status: RecordingStatusSchema,
2428
+ visible_to_clients: z49.boolean(),
2429
+ created_at: IsoDateTimeSchema,
2430
+ updated_at: IsoDateTimeSchema,
2431
+ title: z49.string(),
2432
+ inherits_status: z49.boolean(),
2433
+ type: z49.literal("Question"),
2434
+ url: z49.string().url(),
2435
+ app_url: z49.string().url(),
2436
+ bookmark_url: z49.string().url(),
2437
+ subscription_url: z49.string().url(),
2438
+ parent: RecordingRefSchema,
2439
+ bucket: BucketRefSchema,
2440
+ creator: PersonSummarySchema,
2441
+ paused: z49.boolean(),
2442
+ schedule: QuestionScheduleSchema,
2443
+ answers_count: z49.number().int(),
2444
+ answers_url: z49.string().url()
2445
+ });
2446
+ var QuestionListResponseSchema = z49.array(QuestionSchema);
2447
+ var QuestionListQuerySchema = z49.object({
2448
+ page: z49.coerce.number().int().positive().optional()
2449
+ });
2450
+
2451
+ // src/contract/resources/scheduling/questions.ts
2452
+ var bucketAndQuestionnairePathParams2 = z50.object({
2453
+ bucketId: BasecampIdParamSchema,
2454
+ questionnaireId: BasecampIdParamSchema
2455
+ });
2456
+ var bucketAndQuestionPathParams = z50.object({
2457
+ bucketId: BasecampIdParamSchema,
2458
+ questionId: BasecampIdParamSchema
2459
+ });
2460
+ var questionsRouter = c.router({
2461
+ list: {
2462
+ summary: "List questions",
2463
+ description: "Returns a paginated list of questions in a questionnaire (automatic check-ins).",
2464
+ metadata: {
2465
+ tag: "Questions",
2466
+ operationId: "questions.list",
2467
+ docsPath: "/docs/basecamp-api-specs/sections/questions.md#get-questions"
2468
+ },
2469
+ method: "GET",
2470
+ path: "/buckets/:bucketId/questionnaires/:questionnaireId/questions",
2471
+ pathParams: bucketAndQuestionnairePathParams2,
2472
+ query: QuestionListQuerySchema,
2473
+ responses: {
2474
+ 200: QuestionListResponseSchema
2475
+ }
2476
+ },
2477
+ get: {
2478
+ summary: "Get a question",
2479
+ description: "Returns a single automatic check-in question with its schedule and metadata.",
2480
+ metadata: {
2481
+ tag: "Questions",
2482
+ operationId: "questions.get",
2483
+ docsPath: "/docs/basecamp-api-specs/sections/questions.md#get-a-question"
2484
+ },
2485
+ method: "GET",
2486
+ path: "/buckets/:bucketId/questions/:questionId",
2487
+ pathParams: bucketAndQuestionPathParams,
2488
+ responses: {
2489
+ 200: QuestionSchema
2490
+ }
2491
+ }
2492
+ });
2493
+
2494
+ // src/contract/resources/tasks/todosets.ts
2495
+ import { z as z52 } from "zod";
2496
+
2497
+ // src/contract/schemas/tasks/todosets.ts
2498
+ import { z as z51 } from "zod";
2499
+ var TodoRecordingCoreSchema = z51.object({
2500
+ id: BasecampIdSchema,
2501
+ status: RecordingStatusSchema,
2502
+ visible_to_clients: z51.boolean(),
2503
+ created_at: IsoDateTimeSchema,
2504
+ updated_at: IsoDateTimeSchema,
2505
+ title: z51.string(),
2506
+ inherits_status: z51.boolean(),
2507
+ type: z51.string(),
2508
+ url: z51.string().url(),
2509
+ app_url: z51.string().url(),
2510
+ bookmark_url: z51.string().url().optional(),
2511
+ subscription_url: z51.string().url().optional(),
2512
+ comments_count: z51.number().int().nonnegative().optional(),
2513
+ comments_url: z51.string().url().optional(),
2514
+ position: z51.number().int().nonnegative().optional(),
2515
+ parent: RecordingRefSchema.optional(),
2516
+ bucket: BucketRefSchema,
2517
+ creator: PersonSummarySchema
2518
+ });
2519
+ var TodoSetSchema = TodoRecordingCoreSchema.omit({
2520
+ subscription_url: true,
2521
+ comments_count: true,
2522
+ comments_url: true
2523
+ }).extend({
2524
+ completed: z51.boolean(),
2525
+ completed_ratio: z51.string(),
2526
+ name: z51.string(),
2527
+ todolists_count: z51.number().int().nonnegative(),
2528
+ todolists_url: z51.string().url(),
2529
+ app_todoslists_url: z51.string().url()
2530
+ });
2531
+
2532
+ // src/contract/resources/tasks/todosets.ts
2533
+ var bucketPathParams2 = z52.object({
2534
+ bucketId: BasecampIdParamSchema
2535
+ });
2536
+ var bucketAndTodoSetPathParams = bucketPathParams2.extend({
2537
+ todosetId: BasecampIdParamSchema
2538
+ });
2539
+ var todoSetsRouter = c.router({
2540
+ get: {
2541
+ summary: "Get a to-do set",
2542
+ description: "Return the to-do set container for a project. Use this to discover to-do lists and their groups.",
2543
+ metadata: {
2544
+ tag: "Todo Sets",
2545
+ operationId: "todoSets.get",
2546
+ docsPath: "/docs/basecamp-api-specs/sections/todosets.md#get-to-do-set"
2547
+ },
2548
+ method: "GET",
2549
+ path: "/buckets/:bucketId/todosets/:todosetId",
2550
+ pathParams: bucketAndTodoSetPathParams,
2551
+ responses: {
2552
+ 200: TodoSetSchema
2553
+ }
2554
+ }
2555
+ });
2556
+
2557
+ // src/contract/resources/tasks/todolists.ts
2558
+ import { z as z54 } from "zod";
2559
+
2560
+ // src/contract/schemas/tasks/todolists.ts
2561
+ import { z as z53 } from "zod";
2562
+ var TodoRecordingCoreSchema2 = z53.object({
2563
+ id: BasecampIdSchema,
2564
+ status: RecordingStatusSchema,
2565
+ visible_to_clients: z53.boolean(),
2566
+ created_at: IsoDateTimeSchema,
2567
+ updated_at: IsoDateTimeSchema,
2568
+ title: z53.string(),
2569
+ inherits_status: z53.boolean(),
2570
+ type: z53.string(),
2571
+ url: z53.string().url(),
2572
+ app_url: z53.string().url(),
2573
+ bookmark_url: z53.string().url().optional(),
2574
+ subscription_url: z53.string().url().optional(),
2575
+ comments_count: z53.number().int().nonnegative().optional(),
2576
+ comments_url: z53.string().url().optional(),
2577
+ position: z53.number().int().nonnegative().optional(),
2578
+ parent: RecordingRefSchema.optional(),
2579
+ bucket: BucketRefSchema,
2580
+ creator: PersonSummarySchema
2581
+ });
2582
+ var TodoListBaseSchema = TodoRecordingCoreSchema2.extend({
2583
+ description: HtmlStringSchema.optional(),
2584
+ completed: z53.boolean(),
2585
+ completed_ratio: z53.string(),
2586
+ name: z53.string(),
2587
+ todos_url: z53.string().url(),
2588
+ app_todos_url: z53.string().url()
2589
+ });
2590
+ var TodoTopLevelListSchema = TodoListBaseSchema.extend({
2591
+ groups_url: z53.string().url()
2592
+ });
2593
+ var TodoListGroupSchema = TodoListBaseSchema.extend({
2594
+ group_position_url: z53.string().url()
2595
+ });
2596
+ var TodoListSchema = z53.union([TodoTopLevelListSchema, TodoListGroupSchema]);
2597
+ var TodoListsResponseSchema = z53.array(TodoTopLevelListSchema);
2598
+ var TodoListQuerySchema = z53.object({
2599
+ status: z53.enum(["active", "archived", "trashed"]).or(z53.string()).optional(),
2600
+ page: z53.coerce.number().int().positive().optional()
2601
+ });
2602
+ var TodoListCreateBodySchema = z53.object({
2603
+ name: z53.string().min(1),
2604
+ description: HtmlStringSchema.nullable().optional()
2605
+ });
2606
+ var TodoListUpdateBodySchema = z53.object({
2607
+ name: z53.string().min(1),
2608
+ description: HtmlStringSchema.nullable().optional()
2609
+ });
2610
+
2611
+ // src/contract/resources/tasks/todolists.ts
2612
+ var bucketPathParams3 = z54.object({
2613
+ bucketId: BasecampIdParamSchema
2614
+ });
2615
+ var bucketAndTodoSetPathParams2 = bucketPathParams3.extend({
2616
+ todosetId: BasecampIdParamSchema
2617
+ });
2618
+ var bucketAndTodoListPathParams = bucketPathParams3.extend({
2619
+ todolistId: BasecampIdParamSchema
2620
+ });
2621
+ var todoListsRouter = c.router({
2622
+ list: {
2623
+ summary: "List to-do lists",
2624
+ description: "List active to-do lists within a to-do set. Pagination metadata is exposed via Link headers.",
2625
+ metadata: {
2626
+ tag: "Todo Lists",
2627
+ operationId: "todoLists.list",
2628
+ docsPath: "/docs/basecamp-api-specs/sections/todolists.md#get-to-do-lists"
2629
+ },
2630
+ method: "GET",
2631
+ path: "/buckets/:bucketId/todosets/:todosetId/todolists",
2632
+ pathParams: bucketAndTodoSetPathParams2,
2633
+ query: TodoListQuerySchema.optional(),
2634
+ responses: {
2635
+ 200: TodoListsResponseSchema
2636
+ }
2637
+ },
2638
+ get: {
2639
+ summary: "Get a to-do list",
2640
+ description: "Fetch a to-do list or group. When the list represents a group, the payload includes a group_position_url instead of groups_url.",
2641
+ metadata: {
2642
+ tag: "Todo Lists",
2643
+ operationId: "todoLists.get",
2644
+ docsPath: "/docs/basecamp-api-specs/sections/todolists.md#get-a-to-do-list"
2645
+ },
2646
+ method: "GET",
2647
+ path: "/buckets/:bucketId/todolists/:todolistId",
2648
+ pathParams: bucketAndTodoListPathParams,
2649
+ responses: {
2650
+ 200: TodoListSchema
2651
+ }
2652
+ },
2653
+ create: {
2654
+ summary: "Create a to-do list",
2655
+ description: "Create a new to-do list inside a to-do set. Descriptions accept rich text HTML.",
2656
+ metadata: {
2657
+ tag: "Todo Lists",
2658
+ operationId: "todoLists.create",
2659
+ docsPath: "/docs/basecamp-api-specs/sections/todolists.md#create-a-to-do-list"
2660
+ },
2661
+ method: "POST",
2662
+ path: "/buckets/:bucketId/todosets/:todosetId/todolists",
2663
+ pathParams: bucketAndTodoSetPathParams2,
2664
+ body: TodoListCreateBodySchema,
2665
+ responses: {
2666
+ 201: TodoTopLevelListSchema
2667
+ }
2668
+ },
2669
+ update: {
2670
+ summary: "Update a to-do list",
2671
+ description: "Update the name or description of an existing to-do list. Basecamp requires the name to be present on every update.",
2672
+ metadata: {
2673
+ tag: "Todo Lists",
2674
+ operationId: "todoLists.update",
2675
+ docsPath: "/docs/basecamp-api-specs/sections/todolists.md#update-a-to-do-list"
2676
+ },
2677
+ method: "PUT",
2678
+ path: "/buckets/:bucketId/todolists/:todolistId",
2679
+ pathParams: bucketAndTodoListPathParams,
2680
+ body: TodoListUpdateBodySchema,
2681
+ responses: {
2682
+ 200: TodoListSchema
2683
+ }
2684
+ },
2685
+ trash: {
2686
+ summary: "Trash a to-do list",
2687
+ description: "Move a to-do list or group to the trash. Trashed items can be restored from the Basecamp UI.",
2688
+ metadata: {
2689
+ tag: "Todo Lists",
2690
+ operationId: "todoLists.trash",
2691
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
2692
+ },
2693
+ method: "PUT",
2694
+ path: "/buckets/:bucketId/recordings/:todolistId/status/trashed",
2695
+ pathParams: bucketAndTodoListPathParams,
2696
+ body: c.noBody(),
2697
+ responses: {
2698
+ 204: c.noBody()
2699
+ }
2700
+ }
2701
+ });
2702
+
2703
+ // src/contract/resources/tasks/todolist-groups.ts
2704
+ import { z as z56 } from "zod";
2705
+
2706
+ // src/contract/schemas/tasks/todolist-groups.ts
2707
+ import { z as z55 } from "zod";
2708
+ var TodoRecordingCoreSchema3 = z55.object({
2709
+ id: BasecampIdSchema,
2710
+ status: RecordingStatusSchema,
2711
+ visible_to_clients: z55.boolean(),
2712
+ created_at: IsoDateTimeSchema,
2713
+ updated_at: IsoDateTimeSchema,
2714
+ title: z55.string(),
2715
+ inherits_status: z55.boolean(),
2716
+ type: z55.string(),
2717
+ url: z55.string().url(),
2718
+ app_url: z55.string().url(),
2719
+ bookmark_url: z55.string().url().optional(),
2720
+ subscription_url: z55.string().url().optional(),
2721
+ comments_count: z55.number().int().nonnegative().optional(),
2722
+ comments_url: z55.string().url().optional(),
2723
+ position: z55.number().int().nonnegative().optional(),
2724
+ parent: RecordingRefSchema.optional(),
2725
+ bucket: BucketRefSchema,
2726
+ creator: PersonSummarySchema
2727
+ });
2728
+ var TodoListBaseSchema2 = TodoRecordingCoreSchema3.extend({
2729
+ description: HtmlStringSchema.optional(),
2730
+ completed: z55.boolean(),
2731
+ completed_ratio: z55.string(),
2732
+ name: z55.string(),
2733
+ todos_url: z55.string().url(),
2734
+ app_todos_url: z55.string().url()
2735
+ });
2736
+ var TodoListGroupSchema2 = TodoListBaseSchema2.extend({
2737
+ group_position_url: z55.string().url()
2738
+ });
2739
+ var TodoListSchema2 = TodoListGroupSchema2;
2740
+ var TodoListGroupsResponseSchema = z55.array(TodoListGroupSchema2);
2741
+ var TodoListGroupQuerySchema = z55.object({
2742
+ status: z55.enum(["active", "archived", "trashed"]).or(z55.string()).optional(),
2743
+ page: z55.coerce.number().int().positive().optional()
2744
+ });
2745
+ var TodoListGroupCreateBodySchema = z55.object({
2746
+ name: z55.string().min(1),
2747
+ color: z55.enum([
2748
+ "white",
2749
+ "red",
2750
+ "orange",
2751
+ "yellow",
2752
+ "green",
2753
+ "blue",
2754
+ "aqua",
2755
+ "purple",
2756
+ "gray",
2757
+ "pink",
2758
+ "brown"
2759
+ ]).or(z55.string()).optional()
2760
+ });
2761
+ var TodoListGroupRepositionBodySchema = z55.object({
2762
+ position: z55.number().int().gte(1)
2763
+ });
2764
+
2765
+ // src/contract/resources/tasks/todolist-groups.ts
2766
+ var bucketPathParams4 = z56.object({
2767
+ bucketId: BasecampIdParamSchema
2768
+ });
2769
+ var bucketAndTodoListPathParams2 = bucketPathParams4.extend({
2770
+ todolistId: BasecampIdParamSchema
2771
+ });
2772
+ var bucketAndGroupPathParams = bucketPathParams4.extend({
2773
+ groupId: BasecampIdParamSchema
2774
+ });
2775
+ var todoListGroupsRouter = c.router({
2776
+ list: {
2777
+ summary: "List to-do list groups",
2778
+ description: "List the to-do list groups contained within a to-do list. Use the status filter to browse archived or trashed groups.",
2779
+ metadata: {
2780
+ tag: "Todo Groups",
2781
+ operationId: "todoListGroups.list",
2782
+ docsPath: "/docs/basecamp-api-specs/sections/todolist_groups.md#list-to-do-list-groups"
2783
+ },
2784
+ method: "GET",
2785
+ path: "/buckets/:bucketId/todolists/:todolistId/groups",
2786
+ pathParams: bucketAndTodoListPathParams2,
2787
+ query: TodoListGroupQuerySchema.optional(),
2788
+ responses: {
2789
+ 200: TodoListGroupsResponseSchema
2790
+ }
2791
+ },
2792
+ create: {
2793
+ summary: "Create a to-do list group",
2794
+ description: "Create a nested group inside a to-do list. Groups share the same representation as to-do lists.",
2795
+ metadata: {
2796
+ tag: "Todo Groups",
2797
+ operationId: "todoListGroups.create",
2798
+ docsPath: "/docs/basecamp-api-specs/sections/todolist_groups.md#create-a-to-do-list-group"
2799
+ },
2800
+ method: "POST",
2801
+ path: "/buckets/:bucketId/todolists/:todolistId/groups",
2802
+ pathParams: bucketAndTodoListPathParams2,
2803
+ body: TodoListGroupCreateBodySchema,
2804
+ responses: {
2805
+ 201: TodoListSchema2
2806
+ }
2807
+ },
2808
+ reposition: {
2809
+ summary: "Reposition a to-do list group",
2810
+ description: "Change the position of a to-do list group within its parent list.",
2811
+ metadata: {
2812
+ tag: "Todo Groups",
2813
+ operationId: "todoListGroups.reposition",
2814
+ docsPath: "/docs/basecamp-api-specs/sections/todolist_groups.md#reposition-a-to-do-list-group"
2815
+ },
2816
+ method: "PUT",
2817
+ path: "/buckets/:bucketId/todolists/groups/:groupId/position",
2818
+ pathParams: bucketAndGroupPathParams,
2819
+ body: TodoListGroupRepositionBodySchema,
2820
+ responses: {
2821
+ 204: c.noBody()
2822
+ }
2823
+ }
2824
+ });
2825
+
2826
+ // src/contract/resources/tasks/todos.ts
2827
+ import { z as z58 } from "zod";
2828
+
2829
+ // src/contract/schemas/tasks/todos.ts
2830
+ import { z as z57 } from "zod";
2831
+ var TodoCompletionSchema = z57.object({
2832
+ created_at: IsoDateTimeSchema,
2833
+ creator: PersonSummarySchema
2834
+ });
2835
+ var TodoRecordingCoreSchema4 = z57.object({
2836
+ id: BasecampIdSchema,
2837
+ status: RecordingStatusSchema,
2838
+ visible_to_clients: z57.boolean(),
2839
+ created_at: IsoDateTimeSchema,
2840
+ updated_at: IsoDateTimeSchema,
2841
+ title: z57.string(),
2842
+ inherits_status: z57.boolean(),
2843
+ type: z57.string(),
2844
+ url: z57.string().url(),
2845
+ app_url: z57.string().url(),
2846
+ bookmark_url: z57.string().url().optional(),
2847
+ subscription_url: z57.string().url().optional(),
2848
+ comments_count: z57.number().int().nonnegative().optional(),
2849
+ comments_url: z57.string().url().optional(),
2850
+ position: z57.number().int().nonnegative().optional(),
2851
+ parent: RecordingRefSchema.optional(),
2852
+ bucket: BucketRefSchema,
2853
+ creator: PersonSummarySchema
2854
+ });
2855
+ var TodoSchema = TodoRecordingCoreSchema4.extend({
2856
+ description: HtmlStringSchema.optional(),
2857
+ completed: z57.boolean(),
2858
+ completion: TodoCompletionSchema.optional(),
2859
+ content: z57.string(),
2860
+ starts_on: z57.string().date().nullable().optional(),
2861
+ due_on: z57.string().date().nullable().optional(),
2862
+ assignees: z57.array(PersonSummarySchema),
2863
+ completion_subscribers: z57.array(PersonSummarySchema),
2864
+ completion_url: z57.string().url()
2865
+ });
2866
+ var TodoCollectionResponseSchema = z57.array(TodoSchema);
2867
+ var TodoQuerySchema = z57.object({
2868
+ status: z57.enum(["active", "archived", "trashed"]).or(z57.string()).optional(),
2869
+ completed: z57.coerce.boolean().optional(),
2870
+ page: z57.coerce.number().int().positive().optional()
2871
+ });
2872
+ var TodoCreateBodySchema = z57.object({
2873
+ content: z57.string().min(1),
2874
+ description: HtmlStringSchema.nullable().optional(),
2875
+ assignee_ids: z57.array(BasecampIdSchema).optional(),
2876
+ completion_subscriber_ids: z57.array(BasecampIdSchema).optional(),
2877
+ notify: z57.boolean().optional(),
2878
+ due_on: z57.string().date().nullable().optional(),
2879
+ starts_on: z57.string().date().nullable().optional()
2880
+ });
2881
+ var TodoUpdateBodySchema = z57.object({
2882
+ content: z57.string().min(1),
2883
+ description: HtmlStringSchema.nullable().optional(),
2884
+ assignee_ids: z57.array(BasecampIdSchema).optional(),
2885
+ completion_subscriber_ids: z57.array(BasecampIdSchema).optional(),
2886
+ notify: z57.boolean().optional(),
2887
+ due_on: z57.string().date().nullable().optional(),
2888
+ starts_on: z57.string().date().nullable().optional()
2889
+ });
2890
+ var TodoRepositionBodySchema = z57.object({
2891
+ position: z57.number().int().gte(1)
2892
+ });
2893
+
2894
+ // src/contract/resources/tasks/todos.ts
2895
+ var bucketPathParams5 = z58.object({
2896
+ bucketId: BasecampIdParamSchema
2897
+ });
2898
+ var bucketAndTodoListPathParams3 = bucketPathParams5.extend({
2899
+ todolistId: BasecampIdParamSchema
2900
+ });
2901
+ var bucketAndTodoPathParams = bucketPathParams5.extend({
2902
+ todoId: BasecampIdParamSchema
2903
+ });
2904
+ var todosRouter = c.router({
2905
+ list: {
2906
+ summary: "List to-dos",
2907
+ description: "List pending or completed to-dos within a to-do list. Use the status and completed filters to target archived or finished items.",
2908
+ metadata: {
2909
+ tag: "Todos",
2910
+ operationId: "todos.list",
2911
+ docsPath: "/docs/basecamp-api-specs/sections/todos.md#get-to-dos"
2912
+ },
2913
+ method: "GET",
2914
+ path: "/buckets/:bucketId/todolists/:todolistId/todos",
2915
+ pathParams: bucketAndTodoListPathParams3,
2916
+ query: TodoQuerySchema.optional(),
2917
+ responses: {
2918
+ 200: TodoCollectionResponseSchema
2919
+ }
2920
+ },
2921
+ get: {
2922
+ summary: "Get a to-do",
2923
+ description: "Fetch a single to-do item by its identifier.",
2924
+ metadata: {
2925
+ tag: "Todos",
2926
+ operationId: "todos.get",
2927
+ docsPath: "/docs/basecamp-api-specs/sections/todos.md#get-a-to-do"
2928
+ },
2929
+ method: "GET",
2930
+ path: "/buckets/:bucketId/todos/:todoId",
2931
+ pathParams: bucketAndTodoPathParams,
2932
+ responses: {
2933
+ 200: TodoSchema
2934
+ }
2935
+ },
2936
+ create: {
2937
+ summary: "Create a to-do",
2938
+ description: "Create a to-do inside a to-do list. Rich text HTML is accepted in the description.",
2939
+ metadata: {
2940
+ tag: "Todos",
2941
+ operationId: "todos.create",
2942
+ docsPath: "/docs/basecamp-api-specs/sections/todos.md#create-a-to-do"
2943
+ },
2944
+ method: "POST",
2945
+ path: "/buckets/:bucketId/todolists/:todolistId/todos",
2946
+ pathParams: bucketAndTodoListPathParams3,
2947
+ body: TodoCreateBodySchema,
2948
+ responses: {
2949
+ 201: TodoSchema
2950
+ }
2951
+ },
2952
+ update: {
2953
+ summary: "Update a to-do",
2954
+ description: "Update the content, description, assignees, or scheduling fields of an existing to-do. The content field must always be provided.",
2955
+ metadata: {
2956
+ tag: "Todos",
2957
+ operationId: "todos.update",
2958
+ docsPath: "/docs/basecamp-api-specs/sections/todos.md#update-a-to-do"
2959
+ },
2960
+ method: "PUT",
2961
+ path: "/buckets/:bucketId/todos/:todoId",
2962
+ pathParams: bucketAndTodoPathParams,
2963
+ body: TodoUpdateBodySchema,
2964
+ responses: {
2965
+ 200: TodoSchema
2966
+ }
2967
+ },
2968
+ complete: {
2969
+ summary: "Complete a to-do",
2970
+ description: "Mark a to-do as completed.",
2971
+ metadata: {
2972
+ tag: "Todos",
2973
+ operationId: "todos.complete",
2974
+ docsPath: "/docs/basecamp-api-specs/sections/todos.md#complete-a-to-do"
2975
+ },
2976
+ method: "POST",
2977
+ path: "/buckets/:bucketId/todos/:todoId/completion",
2978
+ pathParams: bucketAndTodoPathParams,
2979
+ body: c.noBody(),
2980
+ responses: {
2981
+ 204: c.noBody()
2982
+ }
2983
+ },
2984
+ uncomplete: {
2985
+ summary: "Uncomplete a to-do",
2986
+ description: "Remove the completion mark from a to-do.",
2987
+ metadata: {
2988
+ tag: "Todos",
2989
+ operationId: "todos.uncomplete",
2990
+ docsPath: "/docs/basecamp-api-specs/sections/todos.md#uncomplete-a-to-do"
2991
+ },
2992
+ method: "DELETE",
2993
+ path: "/buckets/:bucketId/todos/:todoId/completion",
2994
+ pathParams: bucketAndTodoPathParams,
2995
+ body: c.noBody(),
2996
+ responses: {
2997
+ 204: c.noBody()
2998
+ }
2999
+ },
3000
+ reposition: {
3001
+ summary: "Reposition a to-do",
3002
+ description: "Change the position of a to-do within its list.",
3003
+ metadata: {
3004
+ tag: "Todos",
3005
+ operationId: "todos.reposition",
3006
+ docsPath: "/docs/basecamp-api-specs/sections/todos.md#reposition-a-to-do"
3007
+ },
3008
+ method: "PUT",
3009
+ path: "/buckets/:bucketId/todos/:todoId/position",
3010
+ pathParams: bucketAndTodoPathParams,
3011
+ body: TodoRepositionBodySchema,
3012
+ responses: {
3013
+ 204: c.noBody()
3014
+ }
3015
+ },
3016
+ trash: {
3017
+ summary: "Trash a to-do",
3018
+ description: "Move a to-do to the trash queue.",
3019
+ metadata: {
3020
+ tag: "Todos",
3021
+ operationId: "todos.trash",
3022
+ docsPath: "/docs/basecamp-api-specs/sections/recordings.md#trash-a-recording"
3023
+ },
3024
+ method: "PUT",
3025
+ path: "/buckets/:bucketId/recordings/:todoId/status/trashed",
3026
+ pathParams: bucketAndTodoPathParams,
3027
+ body: c.noBody(),
3028
+ responses: {
3029
+ 204: c.noBody()
3030
+ }
3031
+ }
3032
+ });
3033
+
3034
+ // src/contract/index.ts
3035
+ var contract = c.router(
3036
+ {
3037
+ projects: projectsRouter,
3038
+ people: peopleRouter,
3039
+ recordings: recordingsRouter,
3040
+ events: eventsRouter,
3041
+ lineupMarkers: lineupMarkersRouter,
3042
+ todoSets: todoSetsRouter,
3043
+ todoLists: todoListsRouter,
3044
+ todoListGroups: todoListGroupsRouter,
3045
+ todos: todosRouter,
3046
+ messageBoards: messageBoardsRouter,
3047
+ messageTypes: messageTypesRouter,
3048
+ messages: messagesRouter,
3049
+ comments: commentsRouter,
3050
+ campfires: campfiresRouter,
3051
+ inboxes: inboxesRouter,
3052
+ forwards: forwardsRouter,
3053
+ inboxReplies: inboxRepliesRouter,
3054
+ clientApprovals: clientApprovalsRouter,
3055
+ clientCorrespondences: clientCorrespondencesRouter,
3056
+ clientReplies: clientRepliesRouter,
3057
+ clientVisibility: clientVisibilityRouter,
3058
+ schedules: schedulesRouter,
3059
+ scheduleEntries: scheduleEntriesRouter,
3060
+ questionnaires: questionnairesRouter,
3061
+ questions: questionsRouter,
3062
+ documents: documentsRouter,
3063
+ vaults: vaultsRouter,
3064
+ uploads: uploadsRouter,
3065
+ attachments: attachmentsRouter
3066
+ },
3067
+ {
3068
+ strictStatusCodes: true,
3069
+ baseHeaders: z59.object({
3070
+ Authorization: z59.string().min(1),
3071
+ "User-Agent": z59.string().min(1),
3072
+ Accept: z59.literal("application/json").optional()
3073
+ })
3074
+ }
3075
+ );
3076
+
3077
+ // src/fetcher.ts
3078
+ import { tsRestFetchApi } from "@ts-rest/core";
3079
+ var MAX_RETRIES = 20;
3080
+ var BASE_DELAY_MS = 500;
3081
+ var JITTER_MS = 250;
3082
+ var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
3083
+ var parseRetryAfterHeader = (headers) => {
3084
+ const retryAfter = headers.get("Retry-After");
3085
+ if (!retryAfter) {
3086
+ return void 0;
3087
+ }
3088
+ const asSeconds = Number(retryAfter);
3089
+ if (!Number.isNaN(asSeconds)) {
3090
+ return Math.max(0, asSeconds * 1e3);
3091
+ }
3092
+ const parsedDate = Date.parse(retryAfter);
3093
+ if (!Number.isNaN(parsedDate)) {
3094
+ return Math.max(0, parsedDate - Date.now());
3095
+ }
3096
+ return void 0;
3097
+ };
3098
+ var computeBackoffDelay = (attempt, retryAfterMs) => {
3099
+ const linearDelay = BASE_DELAY_MS * attempt;
3100
+ const jitter = Math.random() * JITTER_MS;
3101
+ const computed = linearDelay + jitter;
3102
+ if (retryAfterMs === void 0) {
3103
+ return computed;
3104
+ }
3105
+ return Math.max(computed, retryAfterMs);
3106
+ };
3107
+ async function fetcher(args) {
3108
+ const url = new URL(args.path);
3109
+ if (!url.pathname.endsWith(".json")) {
3110
+ url.pathname = `${url.pathname}.json`;
3111
+ }
3112
+ const pathWithSuffix = url.toString();
3113
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt += 1) {
3114
+ const response = await tsRestFetchApi({
3115
+ ...args,
3116
+ path: pathWithSuffix
3117
+ });
3118
+ if (response.status !== 429) {
3119
+ return response;
3120
+ }
3121
+ if (attempt === MAX_RETRIES) {
3122
+ return response;
3123
+ }
3124
+ const retryAfterMs = parseRetryAfterHeader(response.headers);
3125
+ const delay = computeBackoffDelay(attempt + 1, retryAfterMs);
3126
+ if (delay > 0) {
3127
+ await sleep(delay);
3128
+ }
3129
+ }
3130
+ throw new Error("Exceeded retry attempts for Basecamp API request.");
3131
+ }
3132
+
3133
+ // src/buildClient.ts
3134
+ function buildClient(options) {
3135
+ return tsRestInitClient(contract, {
3136
+ baseUrl: `https://3.basecampapi.com/${options.accountId}`,
3137
+ baseHeaders: {
3138
+ Authorization: `Bearer ${options.bearerToken}`,
3139
+ "User-Agent": options.userAgent,
3140
+ Accept: "application/json",
3141
+ "Content-Type": "application/json"
3142
+ },
3143
+ throwOnUnknownStatus: true,
3144
+ api: fetcher
3145
+ });
3146
+ }
3147
+
3148
+ // src/getBearerToken.ts
3149
+ async function getBearerToken({
3150
+ clientId,
3151
+ clientSecret,
3152
+ refreshToken,
3153
+ userAgent
3154
+ }) {
3155
+ const response = await fetch("https://launchpad.37signals.com/authorization/token", {
3156
+ method: "POST",
3157
+ headers: {
3158
+ "Content-Type": "application/json",
3159
+ "User-Agent": userAgent
3160
+ },
3161
+ body: JSON.stringify({
3162
+ type: "refresh",
3163
+ client_id: clientId,
3164
+ client_secret: clientSecret,
3165
+ refresh_token: refreshToken
3166
+ })
3167
+ });
3168
+ if (!response.ok) {
3169
+ const errorBody = await response.text();
3170
+ throw new Error(`Failed to obtain access token (${response.status}): ${errorBody}`);
3171
+ }
3172
+ const payload = await response.json();
3173
+ return payload.access_token;
3174
+ }
3175
+ export {
3176
+ buildClient,
3177
+ contract,
3178
+ getBearerToken
3179
+ };
3180
+ //# sourceMappingURL=index.mjs.map