@loculabs/api-client 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1075 @@
1
+ interface components {
2
+ schemas: {
3
+ /** @description Task description in multiple formats */
4
+ TaskDescription: {
5
+ /** @description Description content as Markdown */
6
+ markdown: string;
7
+ /** @description Description content as HTML (only included when includeHtml=true) */
8
+ html?: string;
9
+ /**
10
+ * @description ProseMirror JSON document. Root node always has type "doc" with a content array of child nodes.
11
+ * @example {
12
+ * "type": "doc",
13
+ * "content": [
14
+ * {
15
+ * "type": "paragraph",
16
+ * "content": [
17
+ * {
18
+ * "type": "text",
19
+ * "text": "Hello "
20
+ * },
21
+ * {
22
+ * "type": "text",
23
+ * "text": "world",
24
+ * "marks": [
25
+ * {
26
+ * "type": "bold"
27
+ * }
28
+ * ]
29
+ * }
30
+ * ]
31
+ * }
32
+ * ]
33
+ * }
34
+ */
35
+ json?: {
36
+ /**
37
+ * @description Document root type, always "doc"
38
+ * @enum {string}
39
+ */
40
+ type: "doc";
41
+ /** @description Array of child document nodes */
42
+ content: {
43
+ /** @description Node type (e.g., "paragraph", "text", "heading", "bulletList") */
44
+ type: string;
45
+ /** @description Node attributes */
46
+ attrs?: {
47
+ [key: string]: (string | null) | number | boolean;
48
+ };
49
+ /** @description Child nodes (recursive DocumentNode array) */
50
+ content?: Record<string, never>[];
51
+ /** @description Text content (only for text nodes) */
52
+ text?: string;
53
+ /** @description Text marks (bold, italic, links, etc.) - only for text nodes */
54
+ marks?: {
55
+ /** @description Mark type (e.g., "bold", "italic", "link") */
56
+ type: string;
57
+ /** @description Mark attributes */
58
+ attrs?: {
59
+ [key: string]: (string | null) | number | boolean;
60
+ };
61
+ }[];
62
+ }[];
63
+ };
64
+ /** @description Description content as plain text */
65
+ plainText: string;
66
+ } | null;
67
+ LocuTask: {
68
+ id: string;
69
+ name: string;
70
+ done: "completed" | "canceled" | unknown;
71
+ doneAt: number | null;
72
+ createdAt: number;
73
+ parent: {
74
+ id: string;
75
+ order: number | null;
76
+ } | null;
77
+ waiting?: {
78
+ reason?: string;
79
+ waitingAt: number;
80
+ } | null;
81
+ projectId?: string | null;
82
+ cursorAgentUrl?: string | null;
83
+ integrationId: unknown;
84
+ slackLink?: string;
85
+ /**
86
+ * @default locu
87
+ * @enum {string}
88
+ */
89
+ type: "locu";
90
+ description?: components["schemas"]["TaskDescription"];
91
+ };
92
+ LinearTask: {
93
+ id: string;
94
+ name: string;
95
+ done: "completed" | "canceled" | unknown;
96
+ doneAt: number | null;
97
+ createdAt: number;
98
+ parent: {
99
+ id: string;
100
+ order: number | null;
101
+ } | null;
102
+ waiting?: {
103
+ reason?: string;
104
+ waitingAt: number;
105
+ } | null;
106
+ projectId?: string | null;
107
+ cursorAgentUrl?: string | null;
108
+ integrationId: string;
109
+ number: number;
110
+ priority?: number;
111
+ organizationId: string;
112
+ teamId: string;
113
+ description?: components["schemas"]["TaskDescription"];
114
+ assignee: {
115
+ id: string;
116
+ name: string;
117
+ } | null;
118
+ state: {
119
+ id: string;
120
+ type: string;
121
+ };
122
+ url: string;
123
+ identifier: string;
124
+ deletedInLinear: boolean;
125
+ /**
126
+ * @default linear
127
+ * @enum {string}
128
+ */
129
+ type: "linear";
130
+ };
131
+ JiraTask: {
132
+ id: string;
133
+ name: string;
134
+ done: "completed" | "canceled" | unknown;
135
+ doneAt: number | null;
136
+ createdAt: number;
137
+ parent: {
138
+ id: string;
139
+ order: number | null;
140
+ } | null;
141
+ waiting?: {
142
+ reason?: string;
143
+ waitingAt: number;
144
+ } | null;
145
+ projectId: string;
146
+ cursorAgentUrl?: string | null;
147
+ integrationId: string;
148
+ description?: components["schemas"]["TaskDescription"];
149
+ assignee: {
150
+ id: string;
151
+ avatar?: string;
152
+ name: string;
153
+ } | null;
154
+ issueType: {
155
+ id: string;
156
+ name: string;
157
+ icon: string;
158
+ };
159
+ state: {
160
+ id: string;
161
+ name: string;
162
+ statusCategory: {
163
+ id: number;
164
+ key: string;
165
+ name: string;
166
+ color: string;
167
+ };
168
+ };
169
+ url: string;
170
+ identifier: string;
171
+ deletedInJira: boolean;
172
+ /**
173
+ * @default jira
174
+ * @enum {string}
175
+ */
176
+ type: "jira";
177
+ };
178
+ Task: components["schemas"]["LocuTask"] | components["schemas"]["LinearTask"] | components["schemas"]["JiraTask"];
179
+ Note: {
180
+ id: string;
181
+ text: string;
182
+ name: string;
183
+ /** @default null */
184
+ icon: string | null;
185
+ /** @default null */
186
+ color: string | null;
187
+ /** @default null */
188
+ parent: {
189
+ id: string;
190
+ type: "folder" | "virtual-folder";
191
+ } | null;
192
+ createdAt?: number;
193
+ updatedAt?: number;
194
+ /** @description Note content as Markdown */
195
+ markdown: string;
196
+ /** @description Note content as HTML (only included when includeHtml=true) */
197
+ html?: string;
198
+ /**
199
+ * @description ProseMirror JSON document. Root node always has type "doc" with a content array of child nodes.
200
+ * @example {
201
+ * "type": "doc",
202
+ * "content": [
203
+ * {
204
+ * "type": "paragraph",
205
+ * "content": [
206
+ * {
207
+ * "type": "text",
208
+ * "text": "Hello "
209
+ * },
210
+ * {
211
+ * "type": "text",
212
+ * "text": "world",
213
+ * "marks": [
214
+ * {
215
+ * "type": "bold"
216
+ * }
217
+ * ]
218
+ * }
219
+ * ]
220
+ * }
221
+ * ]
222
+ * }
223
+ */
224
+ json?: {
225
+ /**
226
+ * @description Document root type, always "doc"
227
+ * @enum {string}
228
+ */
229
+ type: "doc";
230
+ /** @description Array of child document nodes */
231
+ content: {
232
+ /** @description Node type (e.g., "paragraph", "text", "heading", "bulletList") */
233
+ type: string;
234
+ /** @description Node attributes */
235
+ attrs?: {
236
+ [key: string]: (string | null) | number | boolean;
237
+ };
238
+ /** @description Child nodes (recursive DocumentNode array) */
239
+ content?: Record<string, never>[];
240
+ /** @description Text content (only for text nodes) */
241
+ text?: string;
242
+ /** @description Text marks (bold, italic, links, etc.) - only for text nodes */
243
+ marks?: {
244
+ /** @description Mark type (e.g., "bold", "italic", "link") */
245
+ type: string;
246
+ /** @description Mark attributes */
247
+ attrs?: {
248
+ [key: string]: (string | null) | number | boolean;
249
+ };
250
+ }[];
251
+ }[];
252
+ };
253
+ /** @description Note content as plain text */
254
+ plainText: string;
255
+ };
256
+ NoteListResponse: {
257
+ data: components["schemas"]["Note"][];
258
+ nextCursor: string | null;
259
+ hasMore: boolean;
260
+ };
261
+ ErrorResponse: {
262
+ error: string;
263
+ message: string;
264
+ code?: string;
265
+ };
266
+ CreateNoteRequest: {
267
+ /**
268
+ * Format: uuid
269
+ * @description Optional custom ID for the note
270
+ */
271
+ id?: string;
272
+ /** @description Initial markdown text content */
273
+ text: string;
274
+ /** @description Icon for the note: Lucide icon name (e.g., "FileText") or emoji shortcode (e.g., ":memo:") */
275
+ icon?: string | null;
276
+ /** @description Hex color for the icon (e.g., "#FF5733"). Only applies to Lucide icons, not emojis. */
277
+ color?: string | null;
278
+ /** @description Parent folder ID */
279
+ folderId?: string;
280
+ };
281
+ UpdateNoteRequest: {
282
+ /** @description New text content for the note */
283
+ text?: string;
284
+ /** @description New icon for the note: Lucide icon name (e.g., "FileText") or emoji shortcode (e.g., ":memo:") */
285
+ icon?: string | null;
286
+ /** @description New hex color for the icon (e.g., "#FF5733"). Only applies to Lucide icons, not emojis. */
287
+ color?: string | null;
288
+ /** @description New parent folder ID */
289
+ folderId?: string | null;
290
+ };
291
+ DeleteNoteResponse: {
292
+ success: boolean;
293
+ };
294
+ /** @description Project description in multiple formats */
295
+ ProjectDescription: {
296
+ /** @description Description content as Markdown */
297
+ markdown: string;
298
+ /** @description Description content as HTML (only included when includeHtml=true) */
299
+ html?: string;
300
+ /**
301
+ * @description ProseMirror JSON document. Root node always has type "doc" with a content array of child nodes.
302
+ * @example {
303
+ * "type": "doc",
304
+ * "content": [
305
+ * {
306
+ * "type": "paragraph",
307
+ * "content": [
308
+ * {
309
+ * "type": "text",
310
+ * "text": "Hello "
311
+ * },
312
+ * {
313
+ * "type": "text",
314
+ * "text": "world",
315
+ * "marks": [
316
+ * {
317
+ * "type": "bold"
318
+ * }
319
+ * ]
320
+ * }
321
+ * ]
322
+ * }
323
+ * ]
324
+ * }
325
+ */
326
+ json?: {
327
+ /**
328
+ * @description Document root type, always "doc"
329
+ * @enum {string}
330
+ */
331
+ type: "doc";
332
+ /** @description Array of child document nodes */
333
+ content: {
334
+ /** @description Node type (e.g., "paragraph", "text", "heading", "bulletList") */
335
+ type: string;
336
+ /** @description Node attributes */
337
+ attrs?: {
338
+ [key: string]: (string | null) | number | boolean;
339
+ };
340
+ /** @description Child nodes (recursive DocumentNode array) */
341
+ content?: Record<string, never>[];
342
+ /** @description Text content (only for text nodes) */
343
+ text?: string;
344
+ /** @description Text marks (bold, italic, links, etc.) - only for text nodes */
345
+ marks?: {
346
+ /** @description Mark type (e.g., "bold", "italic", "link") */
347
+ type: string;
348
+ /** @description Mark attributes */
349
+ attrs?: {
350
+ [key: string]: (string | null) | number | boolean;
351
+ };
352
+ }[];
353
+ }[];
354
+ };
355
+ /** @description Description content as plain text */
356
+ plainText: string;
357
+ } | null;
358
+ Project: {
359
+ id: string;
360
+ name: string;
361
+ icon: string | null;
362
+ color: string | null;
363
+ state: "planned" | "completed";
364
+ completedAt?: number | null;
365
+ createdAt: number;
366
+ updatedAt: number;
367
+ description?: components["schemas"]["ProjectDescription"];
368
+ };
369
+ ProjectListResponse: {
370
+ data: components["schemas"]["Project"][];
371
+ nextCursor: string | null;
372
+ hasMore: boolean;
373
+ };
374
+ CreateProjectRequest: {
375
+ /**
376
+ * Format: uuid
377
+ * @description Optional custom ID for the project
378
+ */
379
+ id?: string;
380
+ /** @description Name of the project */
381
+ name: string;
382
+ /** @description Project description in markdown format */
383
+ description?: string;
384
+ /** @description Icon for the project: Lucide icon name (e.g., "Folder") or emoji shortcode (e.g., ":rocket:") */
385
+ icon?: string | null;
386
+ /** @description Hex color for the icon (e.g., "#FF5733"). Only applies to Lucide icons, not emojis. */
387
+ color?: string | null;
388
+ };
389
+ UpdateProjectRequest: {
390
+ /** @description New name for the project */
391
+ name?: string;
392
+ /** @description Project description in markdown format */
393
+ description?: string;
394
+ /** @description New icon for the project: Lucide icon name (e.g., "Folder") or emoji shortcode (e.g., ":rocket:") */
395
+ icon?: string | null;
396
+ /** @description New hex color for the icon (e.g., "#FF5733"). Only applies to Lucide icons, not emojis. */
397
+ color?: string | null;
398
+ /**
399
+ * @description New state for the project
400
+ * @enum {string}
401
+ */
402
+ state?: "planned" | "completed";
403
+ };
404
+ DeleteProjectResponse: {
405
+ success: boolean;
406
+ };
407
+ SessionActivity: {
408
+ /** @enum {string} */
409
+ type: "TASK";
410
+ taskId: string;
411
+ id: string;
412
+ createdAt: number;
413
+ finishedAt: number;
414
+ sessionId: string;
415
+ isManual: boolean;
416
+ } | {
417
+ /** @enum {string} */
418
+ type: "MEETING";
419
+ title: string;
420
+ htmlLink: string;
421
+ meetingId: string;
422
+ calendarId?: string;
423
+ id: string;
424
+ createdAt: number;
425
+ finishedAt: number;
426
+ sessionId: string;
427
+ isManual: boolean;
428
+ } | {
429
+ /** @enum {string} */
430
+ type: "PLANNING";
431
+ id: string;
432
+ createdAt: number;
433
+ finishedAt: number;
434
+ sessionId: string;
435
+ isManual: boolean;
436
+ } | {
437
+ /** @enum {string} */
438
+ type: "WRAP_UP";
439
+ id: string;
440
+ createdAt: number;
441
+ finishedAt: number;
442
+ sessionId: string;
443
+ isManual: boolean;
444
+ };
445
+ Session: {
446
+ /**
447
+ * Format: uuid
448
+ * @description Unique identifier for the session
449
+ */
450
+ id: string;
451
+ /** @description Whether the session was manually created */
452
+ isManual: boolean;
453
+ /** @description Start timestamp (Unix seconds) */
454
+ createdAt: number;
455
+ /** @description End timestamp (Unix seconds) */
456
+ finishedAt: number;
457
+ };
458
+ SessionWithActivities: components["schemas"]["Session"] & {
459
+ /** @description Activities within this session */
460
+ activities: components["schemas"]["SessionActivity"][];
461
+ };
462
+ SessionListResponse: {
463
+ data: components["schemas"]["SessionWithActivities"][];
464
+ nextCursor: string | null;
465
+ hasMore: boolean;
466
+ };
467
+ CreateSessionRequest: {
468
+ /**
469
+ * Format: uuid
470
+ * @description Optional custom ID for the session
471
+ */
472
+ id?: string;
473
+ /** @description Start timestamp (Unix seconds) */
474
+ createdAt: number;
475
+ /** @description End timestamp (Unix seconds) */
476
+ finishedAt: number;
477
+ };
478
+ UpdateSessionRequest: {
479
+ /** @description New start timestamp (Unix seconds) */
480
+ createdAt?: number;
481
+ /** @description New end timestamp (Unix seconds) */
482
+ finishedAt?: number;
483
+ };
484
+ DeleteSessionResponse: {
485
+ success: boolean;
486
+ };
487
+ ActivityListResponse: {
488
+ data: components["schemas"]["SessionActivity"][];
489
+ };
490
+ CreateActivityRequest: {
491
+ /** @description Optional custom ID for the activity */
492
+ id?: string;
493
+ /** @enum {string} */
494
+ type: "TASK";
495
+ /** @description Associated task ID */
496
+ taskId: string;
497
+ /** @description Start timestamp (Unix seconds) */
498
+ createdAt: number;
499
+ /** @description End timestamp (Unix seconds) */
500
+ finishedAt: number;
501
+ };
502
+ UpdateActivityRequest: {
503
+ /** @description New start timestamp (Unix seconds) */
504
+ createdAt?: number;
505
+ /** @description New end timestamp (Unix seconds) */
506
+ finishedAt?: number;
507
+ };
508
+ DeleteActivityResponse: {
509
+ success: boolean;
510
+ };
511
+ TaskListResponse: {
512
+ data: components["schemas"]["Task"][];
513
+ nextCursor: string | null;
514
+ hasMore: boolean;
515
+ };
516
+ TaskBySection: {
517
+ /** Format: uuid */
518
+ taskId: string;
519
+ /** @enum {string} */
520
+ section: "today" | "sooner" | "later";
521
+ order: number;
522
+ task: components["schemas"]["Task"];
523
+ };
524
+ TaskSectionsResponse: {
525
+ today: components["schemas"]["TaskBySection"][];
526
+ sooner: components["schemas"]["TaskBySection"][];
527
+ later: components["schemas"]["TaskBySection"][];
528
+ };
529
+ TaskSubtasksResponse: {
530
+ data: components["schemas"]["Task"][];
531
+ nextCursor: string | null;
532
+ hasMore: boolean;
533
+ };
534
+ CreateTaskRequest: {
535
+ /**
536
+ * Format: uuid
537
+ * @description Optional custom ID for the task
538
+ */
539
+ id?: string;
540
+ /** @description Task name */
541
+ name: string;
542
+ /** @description Task description in markdown format */
543
+ description?: string;
544
+ /**
545
+ * Format: uuid
546
+ * @description Parent task ID for subtasks
547
+ */
548
+ parentId?: string;
549
+ /**
550
+ * Format: uuid
551
+ * @description Project to assign the task to
552
+ */
553
+ projectId?: string;
554
+ /**
555
+ * @description Section to place the task in. Required for root tasks (when parentId is not provided). Ignored for subtasks.
556
+ * @enum {string}
557
+ */
558
+ section?: "today" | "sooner" | "later";
559
+ };
560
+ UpdateTaskRequest: {
561
+ /** @description Task name */
562
+ name?: string;
563
+ /** @description Task description in markdown format */
564
+ description?: string;
565
+ /** @description Task completion status */
566
+ done?: "completed" | "canceled" | unknown | unknown;
567
+ /**
568
+ * Format: uuid
569
+ * @description Project to assign the task to
570
+ */
571
+ projectId?: string | null;
572
+ /** @description Mark task as waiting */
573
+ waiting?: {
574
+ reason?: string;
575
+ } | null;
576
+ };
577
+ DeleteTaskResponse: {
578
+ success: boolean;
579
+ };
580
+ TimerState: {
581
+ /**
582
+ * @description Current timer state
583
+ * @enum {string}
584
+ */
585
+ state: "IDLE" | "ACTIVE" | "PAUSED";
586
+ /** @description Planned duration in seconds (only present when not IDLE) */
587
+ duration?: number;
588
+ /** @description ID of the task being worked on (only present when ACTIVE with a task) */
589
+ currentTaskId?: string;
590
+ /** @description When the timer was started as Unix timestamp in seconds (only present when not IDLE) */
591
+ startedAt?: number;
592
+ };
593
+ StartTimerRequest: {
594
+ /** @description Duration in seconds (must be positive) */
595
+ duration: number;
596
+ /** @description Optional task ID to start working on */
597
+ taskId?: string;
598
+ };
599
+ StopTimerSession: {
600
+ /** @description Unique identifier for the session */
601
+ id: string;
602
+ /** @description Whether the session was manually created */
603
+ isManual: boolean;
604
+ /** @description Start timestamp (Unix seconds) */
605
+ createdAt: number;
606
+ /** @description End timestamp (Unix seconds) */
607
+ finishedAt: number;
608
+ };
609
+ StopTimerResponse: {
610
+ /** @description The completed sessions that were created */
611
+ sessions: components["schemas"]["StopTimerSession"][];
612
+ };
613
+ Webhook: {
614
+ /**
615
+ * Format: uuid
616
+ * @description Unique identifier for the webhook
617
+ */
618
+ id: string;
619
+ /**
620
+ * Format: uri
621
+ * @description URL to receive webhook payloads
622
+ */
623
+ url: string;
624
+ /** @description Entity types to listen for (task, project, timer, note) */
625
+ entityTypes: ("task" | "project" | "timer" | "note")[];
626
+ /** @description Event types to listen for (created, updated, deleted) */
627
+ eventTypes: ("created" | "updated" | "deleted")[];
628
+ /** @description Whether the webhook is active */
629
+ isActive: boolean;
630
+ /**
631
+ * Format: date-time
632
+ * @description Creation timestamp
633
+ */
634
+ createdAt: string;
635
+ /**
636
+ * Format: date-time
637
+ * @description Last update timestamp
638
+ */
639
+ updatedAt: string;
640
+ };
641
+ WebhookListResponse: {
642
+ data: components["schemas"]["Webhook"][];
643
+ nextCursor: string | null;
644
+ hasMore: boolean;
645
+ };
646
+ WebhookWithSecret: components["schemas"]["Webhook"] & {
647
+ /** @description Secret for verifying webhook signatures (only shown once) */
648
+ secret: string;
649
+ };
650
+ CreateWebhookRequest: {
651
+ /**
652
+ * Format: uri
653
+ * @description URL to receive webhook payloads
654
+ */
655
+ url: string;
656
+ /**
657
+ * @description Entity types to listen for
658
+ * @default [
659
+ * "task",
660
+ * "project",
661
+ * "timer",
662
+ * "note"
663
+ * ]
664
+ */
665
+ entityTypes: ("task" | "project" | "timer" | "note")[];
666
+ /**
667
+ * @description Event types to listen for
668
+ * @default [
669
+ * "created",
670
+ * "updated",
671
+ * "deleted"
672
+ * ]
673
+ */
674
+ eventTypes: ("created" | "updated" | "deleted")[];
675
+ };
676
+ UpdateWebhookRequest: {
677
+ /**
678
+ * Format: uri
679
+ * @description New URL for webhook payloads
680
+ */
681
+ url?: string;
682
+ /** @description New entity types to listen for */
683
+ entityTypes?: ("task" | "project" | "timer" | "note")[];
684
+ /** @description New event types to listen for */
685
+ eventTypes?: ("created" | "updated" | "deleted")[];
686
+ /** @description Enable or disable the webhook */
687
+ isActive?: boolean;
688
+ };
689
+ DeleteWebhookResponse: {
690
+ success: boolean;
691
+ };
692
+ WebhookDelivery: {
693
+ /**
694
+ * Format: uuid
695
+ * @description Delivery ID
696
+ */
697
+ id: string;
698
+ /**
699
+ * Format: uuid
700
+ * @description Associated webhook ID
701
+ */
702
+ webhookId: string;
703
+ /**
704
+ * @description Delivery status
705
+ * @enum {string}
706
+ */
707
+ status: "pending" | "success" | "failed";
708
+ /** @description Number of delivery attempts */
709
+ attemptNumber: number;
710
+ /** @description HTTP response status code */
711
+ responseStatus: number | null;
712
+ /** @description Error message if failed */
713
+ errorMessage: string | null;
714
+ /**
715
+ * Format: date-time
716
+ * @description Delivery creation timestamp
717
+ */
718
+ createdAt: string;
719
+ /**
720
+ * Format: date-time
721
+ * @description Delivery completion timestamp
722
+ */
723
+ completedAt: string | null;
724
+ };
725
+ WebhookDeliveryListResponse: {
726
+ data: components["schemas"]["WebhookDelivery"][];
727
+ nextCursor: string | null;
728
+ hasMore: boolean;
729
+ };
730
+ RotateSecretResponse: {
731
+ /** @description New webhook secret */
732
+ secret: string;
733
+ };
734
+ };
735
+ responses: never;
736
+ parameters: never;
737
+ requestBodies: never;
738
+ headers: never;
739
+ pathItems: never;
740
+ }
741
+
742
+ /**
743
+ * Re-export types from the generated OpenAPI types.
744
+ * These provide typed access to the Locu API.
745
+ */
746
+
747
+ type Task = components["schemas"]["Task"];
748
+ type LocuTask = components["schemas"]["LocuTask"];
749
+ type LinearTask = components["schemas"]["LinearTask"];
750
+ type JiraTask = components["schemas"]["JiraTask"];
751
+ type TaskDescription = components["schemas"]["TaskDescription"];
752
+ type CreateTaskRequest = components["schemas"]["CreateTaskRequest"];
753
+ type UpdateTaskRequest = components["schemas"]["UpdateTaskRequest"];
754
+ type TaskListResponse = components["schemas"]["TaskListResponse"];
755
+ type TaskBySection = components["schemas"]["TaskBySection"];
756
+ type TaskSectionsResponse = components["schemas"]["TaskSectionsResponse"];
757
+ type DeleteTaskResponse = components["schemas"]["DeleteTaskResponse"];
758
+ type Project = components["schemas"]["Project"];
759
+ type ProjectDescription = components["schemas"]["ProjectDescription"];
760
+ type CreateProjectRequest = components["schemas"]["CreateProjectRequest"];
761
+ type UpdateProjectRequest = components["schemas"]["UpdateProjectRequest"];
762
+ type ProjectListResponse = components["schemas"]["ProjectListResponse"];
763
+ type DeleteProjectResponse = components["schemas"]["DeleteProjectResponse"];
764
+ type Note = components["schemas"]["Note"];
765
+ type CreateNoteRequest = components["schemas"]["CreateNoteRequest"];
766
+ type UpdateNoteRequest = components["schemas"]["UpdateNoteRequest"];
767
+ type NoteListResponse = components["schemas"]["NoteListResponse"];
768
+ type DeleteNoteResponse = components["schemas"]["DeleteNoteResponse"];
769
+ type Session = components["schemas"]["Session"];
770
+ type SessionWithActivities = components["schemas"]["SessionWithActivities"];
771
+ type SessionActivity = components["schemas"]["SessionActivity"];
772
+ type CreateSessionRequest = components["schemas"]["CreateSessionRequest"];
773
+ type UpdateSessionRequest = components["schemas"]["UpdateSessionRequest"];
774
+ type SessionListResponse = components["schemas"]["SessionListResponse"];
775
+ type DeleteSessionResponse = components["schemas"]["DeleteSessionResponse"];
776
+ type CreateActivityRequest = components["schemas"]["CreateActivityRequest"];
777
+ type UpdateActivityRequest = components["schemas"]["UpdateActivityRequest"];
778
+ type ActivityListResponse = components["schemas"]["ActivityListResponse"];
779
+ type DeleteActivityResponse = components["schemas"]["DeleteActivityResponse"];
780
+ type TimerState = components["schemas"]["TimerState"];
781
+ type StartTimerRequest = components["schemas"]["StartTimerRequest"];
782
+ type StopTimerResponse = components["schemas"]["StopTimerResponse"];
783
+ type StopTimerSession = components["schemas"]["StopTimerSession"];
784
+ type Webhook = components["schemas"]["Webhook"];
785
+ type WebhookWithSecret = components["schemas"]["WebhookWithSecret"];
786
+ type CreateWebhookRequest = components["schemas"]["CreateWebhookRequest"];
787
+ type UpdateWebhookRequest = components["schemas"]["UpdateWebhookRequest"];
788
+ type WebhookListResponse = components["schemas"]["WebhookListResponse"];
789
+ type WebhookDelivery = components["schemas"]["WebhookDelivery"];
790
+ type WebhookDeliveryListResponse = components["schemas"]["WebhookDeliveryListResponse"];
791
+ type RotateSecretResponse = components["schemas"]["RotateSecretResponse"];
792
+ type DeleteWebhookResponse = components["schemas"]["DeleteWebhookResponse"];
793
+ type ErrorResponse = components["schemas"]["ErrorResponse"];
794
+ type ApiError = ErrorResponse;
795
+ type WebhookPayload<T = unknown> = {
796
+ /** Event type, e.g. "task.created", "project.updated" */
797
+ event: string;
798
+ /** ISO 8601 timestamp when the event occurred */
799
+ timestamp: string;
800
+ /** The entity data that triggered the event */
801
+ data: T;
802
+ };
803
+ type PaginatedResponse<T> = {
804
+ data: T[];
805
+ nextCursor: string | null;
806
+ hasMore: boolean;
807
+ };
808
+ type PaginationParams = {
809
+ limit?: number;
810
+ cursor?: string;
811
+ };
812
+ type TaskListParams = PaginationParams & {
813
+ done?: "true" | "false";
814
+ projectId?: string;
815
+ parentId?: string;
816
+ section?: "today" | "sooner" | "later";
817
+ doneAfter?: string;
818
+ doneBefore?: string;
819
+ includeHtml?: boolean | null;
820
+ };
821
+ type TaskSectionsParams = {
822
+ projectId?: string;
823
+ includeHtml?: boolean | null;
824
+ };
825
+ type SubtaskListParams = PaginationParams & {
826
+ done?: "true" | "false";
827
+ includeHtml?: boolean | null;
828
+ };
829
+ type ProjectListParams = PaginationParams & {
830
+ state?: "planned" | "completed";
831
+ includeHtml?: boolean | null;
832
+ };
833
+ type NoteListParams = PaginationParams & {
834
+ folderId?: string;
835
+ includeHtml?: boolean | null;
836
+ };
837
+ type SessionListParams = PaginationParams & {
838
+ startAfter?: string;
839
+ startBefore?: string;
840
+ includeActivities?: boolean | null;
841
+ };
842
+ type WebhookListParams = PaginationParams & {
843
+ isActive?: "true" | "false";
844
+ };
845
+
846
+ type LocuClientConfig = {
847
+ /** API base URL (defaults to https://api.locu.app/api/v1) */
848
+ baseUrl?: string;
849
+ /** Personal Access Token for authentication */
850
+ token: string;
851
+ /** Custom fetch implementation (defaults to global fetch) */
852
+ fetch?: typeof fetch;
853
+ };
854
+ declare class LocuApiError extends Error {
855
+ status: number;
856
+ code?: string;
857
+ constructor(message: string, status: number, code?: string);
858
+ }
859
+ declare const createLocuClient: (config: LocuClientConfig) => {
860
+ tasks: {
861
+ /** List all tasks */
862
+ list: (params?: TaskListParams) => Promise<PaginatedResponse<Task>>;
863
+ /** Get a single task by ID */
864
+ get: (id: string) => Promise<Task>;
865
+ /** Create a new task */
866
+ create: (data: CreateTaskRequest) => Promise<Task>;
867
+ /** Update an existing task */
868
+ update: (id: string, data: UpdateTaskRequest) => Promise<Task>;
869
+ /** Delete a task */
870
+ delete: (id: string) => Promise<{
871
+ success: boolean;
872
+ }>;
873
+ /** Get tasks organized by section (today, sooner, later) */
874
+ sections: (params?: TaskSectionsParams) => Promise<TaskSectionsResponse>;
875
+ /** List subtasks for a task */
876
+ subtasks: (id: string, params?: SubtaskListParams) => Promise<PaginatedResponse<Task>>;
877
+ /** Create a subtask under a parent task */
878
+ createSubtask: (parentId: string, data: Omit<CreateTaskRequest, "parentId" | "section">) => Promise<Task>;
879
+ };
880
+ projects: {
881
+ /** List all projects */
882
+ list: (params?: ProjectListParams) => Promise<PaginatedResponse<Project>>;
883
+ /** Get a single project by ID */
884
+ get: (id: string) => Promise<Project>;
885
+ /** Create a new project */
886
+ create: (data: CreateProjectRequest) => Promise<Project>;
887
+ /** Update an existing project */
888
+ update: (id: string, data: UpdateProjectRequest) => Promise<Project>;
889
+ /** Delete a project */
890
+ delete: (id: string) => Promise<{
891
+ success: boolean;
892
+ }>;
893
+ };
894
+ notes: {
895
+ /** List all notes */
896
+ list: (params?: NoteListParams) => Promise<PaginatedResponse<Note>>;
897
+ /** Get a single note by ID */
898
+ get: (id: string) => Promise<Note>;
899
+ /** Create a new note */
900
+ create: (data: CreateNoteRequest) => Promise<Note>;
901
+ /** Update an existing note */
902
+ update: (id: string, data: UpdateNoteRequest) => Promise<Note>;
903
+ /** Delete a note */
904
+ delete: (id: string) => Promise<{
905
+ success: boolean;
906
+ }>;
907
+ };
908
+ sessions: {
909
+ /** List all sessions */
910
+ list: (params?: SessionListParams) => Promise<PaginatedResponse<SessionWithActivities>>;
911
+ /** Get a single session by ID */
912
+ get: (id: string) => Promise<SessionWithActivities>;
913
+ /** Create a new session */
914
+ create: (data: CreateSessionRequest) => Promise<Session>;
915
+ /** Update an existing session */
916
+ update: (id: string, data: UpdateSessionRequest) => Promise<Session>;
917
+ /** Delete a session */
918
+ delete: (id: string) => Promise<{
919
+ success: boolean;
920
+ }>;
921
+ activities: {
922
+ /** List activities for a session */
923
+ list: (sessionId: string) => Promise<{
924
+ data: SessionActivity[];
925
+ }>;
926
+ /** Create a new activitie */
927
+ create: (sessionId: string, data: CreateActivityRequest) => Promise<SessionActivity>;
928
+ /** Update an activitie */
929
+ update: (sessionId: string, activityId: string, data: UpdateActivityRequest) => Promise<SessionActivity>;
930
+ /** Delete an activitie */
931
+ delete: (sessionId: string, activityId: string) => Promise<{
932
+ success: boolean;
933
+ }>;
934
+ };
935
+ };
936
+ webhooks: {
937
+ /** List all webhooks */
938
+ list: (params?: WebhookListParams) => Promise<PaginatedResponse<Webhook>>;
939
+ /** Get a single webhook by ID */
940
+ get: (id: string) => Promise<Webhook>;
941
+ /** Create a new webhook */
942
+ create: (data: CreateWebhookRequest) => Promise<WebhookWithSecret>;
943
+ /** Update an existing webhook */
944
+ update: (id: string, data: UpdateWebhookRequest) => Promise<Webhook>;
945
+ /** Delete a webhook */
946
+ delete: (id: string) => Promise<{
947
+ success: boolean;
948
+ }>;
949
+ /** Rotate webhook secret */
950
+ rotateSecret: (id: string) => Promise<{
951
+ secret: string;
952
+ }>;
953
+ /** List deliveries for a webhook */
954
+ deliveries: (id: string, params?: PaginationParams) => Promise<PaginatedResponse<WebhookDelivery>>;
955
+ };
956
+ timer: {
957
+ /** Get current timer state */
958
+ get: () => Promise<TimerState>;
959
+ /** Start a new timer */
960
+ start: (data?: StartTimerRequest) => Promise<TimerState>;
961
+ /** Pause the running timer */
962
+ pause: () => Promise<TimerState>;
963
+ /** Resume a paused timer */
964
+ continue: () => Promise<TimerState>;
965
+ /** Stop timer and save sessions */
966
+ stop: () => Promise<StopTimerResponse>;
967
+ };
968
+ };
969
+ type LocuClient = ReturnType<typeof createLocuClient>;
970
+
971
+ type WebhookSignatureResult = {
972
+ valid: true;
973
+ } | {
974
+ valid: false;
975
+ error: string;
976
+ };
977
+ type ParsedWebhookSignature = {
978
+ timestamp: number;
979
+ signature: string;
980
+ };
981
+ type VerifyWebhookOptions = {
982
+ /** Maximum age of signature in seconds (default: 300 = 5 minutes) */
983
+ maxAge?: number;
984
+ };
985
+ /**
986
+ * Parse a webhook signature header into its components.
987
+ *
988
+ * The signature header format is: `t=<timestamp>,v1=<hex_signature>`
989
+ *
990
+ * @param signatureHeader - The X-Webhook-Signature header value
991
+ * @returns Parsed timestamp and signature, or null if invalid format
992
+ *
993
+ * @example
994
+ * ```typescript
995
+ * const parsed = parseWebhookSignature(request.headers['x-webhook-signature'])
996
+ * if (parsed) {
997
+ * console.log('Timestamp:', parsed.timestamp)
998
+ * console.log('Signature:', parsed.signature)
999
+ * }
1000
+ * ```
1001
+ */
1002
+ declare const parseWebhookSignature: (signatureHeader: string) => ParsedWebhookSignature | null;
1003
+ /**
1004
+ * Verify a webhook signature using HMAC-SHA256.
1005
+ *
1006
+ * This function verifies that a webhook payload was signed by Locu using your webhook secret.
1007
+ * It also checks that the signature timestamp is not too old to prevent replay attacks.
1008
+ *
1009
+ * @param secret - Your webhook secret (starts with `whsec_`)
1010
+ * @param signatureHeader - The X-Webhook-Signature header value
1011
+ * @param body - The raw request body as a string
1012
+ * @param options - Optional verification settings
1013
+ * @returns Object with `valid: true` if valid, or `valid: false` with an error message
1014
+ *
1015
+ * @example
1016
+ * ```typescript
1017
+ * import { verifyWebhookSignature } from '@locu/api-client'
1018
+ *
1019
+ * app.post('/webhooks/locu', (req, res) => {
1020
+ * const result = verifyWebhookSignature(
1021
+ * process.env.LOCU_WEBHOOK_SECRET,
1022
+ * req.headers['x-webhook-signature'],
1023
+ * req.body, // raw body string
1024
+ * { maxAge: 300 } // 5 minutes
1025
+ * )
1026
+ *
1027
+ * if (!result.valid) {
1028
+ * return res.status(401).json({ error: result.error })
1029
+ * }
1030
+ *
1031
+ * // Process the webhook
1032
+ * const payload = JSON.parse(req.body)
1033
+ * console.log('Received event:', payload.event)
1034
+ * })
1035
+ * ```
1036
+ */
1037
+ declare const verifyWebhookSignature: (secret: string, signatureHeader: string, body: string, options?: VerifyWebhookOptions) => WebhookSignatureResult;
1038
+ /**
1039
+ * Parse a webhook payload from a JSON string.
1040
+ *
1041
+ * @param body - The raw request body as a JSON string
1042
+ * @returns The parsed webhook payload
1043
+ *
1044
+ * @example
1045
+ * ```typescript
1046
+ * import { parseWebhookPayload, TaskWebhookPayload } from '@locu/api-client'
1047
+ *
1048
+ * const payload = parseWebhookPayload<TaskWebhookPayload>(req.body)
1049
+ * console.log('Event:', payload.event) // e.g., "task.created"
1050
+ * console.log('Task name:', payload.data.name)
1051
+ * ```
1052
+ */
1053
+ declare const parseWebhookPayload: <T = unknown>(body: string) => WebhookPayload<T>;
1054
+ /**
1055
+ * Generate a webhook signature for testing purposes.
1056
+ *
1057
+ * This is useful for testing your webhook handlers locally.
1058
+ *
1059
+ * @param secret - Your webhook secret
1060
+ * @param timestamp - Unix timestamp in seconds
1061
+ * @param body - The request body as a string
1062
+ * @returns The signature header value in format `t=<timestamp>,v1=<signature>`
1063
+ *
1064
+ * @example
1065
+ * ```typescript
1066
+ * import { generateWebhookSignature } from '@locu/api-client'
1067
+ *
1068
+ * const body = JSON.stringify({ event: 'task.created', timestamp: '...', data: {...} })
1069
+ * const signature = generateWebhookSignature('whsec_...', Math.floor(Date.now() / 1000), body)
1070
+ * // Use signature for testing your webhook handler
1071
+ * ```
1072
+ */
1073
+ declare const generateWebhookSignature: (secret: string, timestamp: number, body: string) => string;
1074
+
1075
+ export { type ActivityListResponse, type ApiError, type CreateActivityRequest, type CreateNoteRequest, type CreateProjectRequest, type CreateSessionRequest, type CreateTaskRequest, type CreateWebhookRequest, type DeleteActivityResponse, type DeleteNoteResponse, type DeleteProjectResponse, type DeleteSessionResponse, type DeleteTaskResponse, type DeleteWebhookResponse, type ErrorResponse, type JiraTask, type LinearTask, LocuApiError, type LocuClient, type LocuClientConfig, type LocuTask, type Note, type NoteListParams, type NoteListResponse, type PaginatedResponse, type PaginationParams, type ParsedWebhookSignature, type Project, type ProjectDescription, type ProjectListParams, type ProjectListResponse, type RotateSecretResponse, type Session, type SessionActivity, type SessionListParams, type SessionListResponse, type SessionWithActivities, type StartTimerRequest, type StopTimerResponse, type StopTimerSession, type SubtaskListParams, type Task, type TaskBySection, type TaskDescription, type TaskListParams, type TaskListResponse, type TaskSectionsParams, type TaskSectionsResponse, type TimerState, type UpdateActivityRequest, type UpdateNoteRequest, type UpdateProjectRequest, type UpdateSessionRequest, type UpdateTaskRequest, type UpdateWebhookRequest, type VerifyWebhookOptions, type Webhook, type WebhookDelivery, type WebhookDeliveryListResponse, type WebhookListParams, type WebhookListResponse, type WebhookPayload, type WebhookSignatureResult, type WebhookWithSecret, createLocuClient, generateWebhookSignature, parseWebhookPayload, parseWebhookSignature, verifyWebhookSignature };