@getlatedev/node 0.1.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,4162 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ export type AccountGetResponse = {
4
+ account?: SocialAccount;
5
+ };
6
+
7
+ export type AccountsListResponse = {
8
+ accounts?: Array<SocialAccount>;
9
+ /**
10
+ * Whether user has analytics add-on access
11
+ */
12
+ hasAnalyticsAccess?: boolean;
13
+ };
14
+
15
+ export type AccountWithFollowerStats = SocialAccount & {
16
+ profilePicture?: string;
17
+ /**
18
+ * Current follower count
19
+ */
20
+ currentFollowers?: number;
21
+ lastUpdated?: string;
22
+ /**
23
+ * Follower change over period
24
+ */
25
+ growth?: number;
26
+ /**
27
+ * Percentage growth
28
+ */
29
+ growthPercentage?: number;
30
+ /**
31
+ * Number of historical snapshots
32
+ */
33
+ dataPoints?: number;
34
+ };
35
+
36
+ export type AnalyticsListResponse = {
37
+ overview?: AnalyticsOverview;
38
+ posts?: Array<{
39
+ _id?: string;
40
+ content?: string;
41
+ scheduledFor?: string;
42
+ publishedAt?: string;
43
+ status?: string;
44
+ analytics?: PostAnalytics;
45
+ platforms?: Array<PlatformAnalytics>;
46
+ platform?: string;
47
+ platformPostUrl?: string;
48
+ isExternal?: boolean;
49
+ thumbnailUrl?: string;
50
+ mediaType?: 'image' | 'video' | 'gif' | 'document';
51
+ mediaItems?: Array<MediaItem>;
52
+ }>;
53
+ pagination?: Pagination;
54
+ /**
55
+ * Connected social accounts (followerCount and followersLastUpdated only included if user has analytics add-on)
56
+ */
57
+ accounts?: Array<SocialAccount>;
58
+ /**
59
+ * Whether user has analytics add-on access
60
+ */
61
+ hasAnalyticsAccess?: boolean;
62
+ };
63
+
64
+ export type AnalyticsOverview = {
65
+ totalPosts?: number;
66
+ publishedPosts?: number;
67
+ scheduledPosts?: number;
68
+ lastSync?: string;
69
+ };
70
+
71
+ export type AnalyticsSinglePostResponse = {
72
+ postId?: string;
73
+ status?: string;
74
+ content?: string;
75
+ scheduledFor?: string;
76
+ publishedAt?: string;
77
+ analytics?: PostAnalytics;
78
+ platformAnalytics?: Array<PlatformAnalytics>;
79
+ platform?: string;
80
+ platformPostUrl?: string;
81
+ isExternal?: boolean;
82
+ };
83
+
84
+ export type ApiKey = {
85
+ id?: string;
86
+ name?: string;
87
+ keyPreview?: string;
88
+ expiresAt?: string;
89
+ createdAt?: string;
90
+ /**
91
+ * Returned only once, on creation
92
+ */
93
+ key?: string;
94
+ };
95
+
96
+ export type CaptionResponse = {
97
+ caption?: string;
98
+ };
99
+
100
+ export type DownloadFormat = {
101
+ formatId?: string;
102
+ ext?: string;
103
+ resolution?: string;
104
+ filesize?: number;
105
+ quality?: string;
106
+ };
107
+
108
+ export type DownloadResponse = {
109
+ url?: string;
110
+ title?: string;
111
+ thumbnail?: string;
112
+ duration?: number;
113
+ formats?: Array<DownloadFormat>;
114
+ };
115
+
116
+ export type ErrorResponse = {
117
+ error?: string;
118
+ details?: {
119
+ [key: string]: unknown;
120
+ };
121
+ };
122
+
123
+ /**
124
+ * Constraints:
125
+ * - Posts cannot mix videos and images.
126
+ * - Multiple images supported via attached_media (up to 10 images for feed posts).
127
+ * - Multiple videos in the same post are not supported.
128
+ * - Stories require media (single image or video); text captions are not displayed with stories.
129
+ * - Stories are ephemeral (disappear after 24 hours).
130
+ *
131
+ */
132
+ export type FacebookPlatformData = {
133
+ /**
134
+ * Set to 'story' to publish as a Facebook Page Story (24-hour ephemeral content). Requires media.
135
+ */
136
+ contentType?: 'story';
137
+ /**
138
+ * Optional first comment to post immediately after publishing (feed posts only, not stories)
139
+ */
140
+ firstComment?: string;
141
+ /**
142
+ * Target Facebook Page ID. If omitted, uses the selected/default page on the connection.
143
+ */
144
+ pageId?: string;
145
+ };
146
+
147
+ /**
148
+ * Set to 'story' to publish as a Facebook Page Story (24-hour ephemeral content). Requires media.
149
+ */
150
+ export type contentType = 'story';
151
+
152
+ export type FollowerStatsResponse = {
153
+ accounts?: Array<AccountWithFollowerStats>;
154
+ dateRange?: {
155
+ from?: string;
156
+ to?: string;
157
+ };
158
+ aggregation?: 'daily' | 'weekly' | 'monthly';
159
+ };
160
+
161
+ export type aggregation = 'daily' | 'weekly' | 'monthly';
162
+
163
+ /**
164
+ * Google Business Profile post settings:
165
+ * - Posts support text content and a single image (no videos)
166
+ * - Images must be publicly accessible URLs
167
+ * - Call-to-action buttons drive user engagement
168
+ * - Posts appear on your Google Business Profile and in Google Search/Maps
169
+ *
170
+ */
171
+ export type GoogleBusinessPlatformData = {
172
+ /**
173
+ * Optional call-to-action button displayed on the post
174
+ */
175
+ callToAction?: {
176
+ /**
177
+ * Button action type:
178
+ * - LEARN_MORE: Link to more information
179
+ * - BOOK: Booking/reservation link
180
+ * - ORDER: Online ordering link
181
+ * - SHOP: E-commerce/shopping link
182
+ * - SIGN_UP: Registration/signup link
183
+ * - CALL: Phone call action
184
+ *
185
+ */
186
+ type: 'LEARN_MORE' | 'BOOK' | 'ORDER' | 'SHOP' | 'SIGN_UP' | 'CALL';
187
+ /**
188
+ * Destination URL for the CTA button (required when callToAction is provided)
189
+ */
190
+ url: string;
191
+ };
192
+ };
193
+
194
+ /**
195
+ * Button action type:
196
+ * - LEARN_MORE: Link to more information
197
+ * - BOOK: Booking/reservation link
198
+ * - ORDER: Online ordering link
199
+ * - SHOP: E-commerce/shopping link
200
+ * - SIGN_UP: Registration/signup link
201
+ * - CALL: Phone call action
202
+ *
203
+ */
204
+ export type type = 'LEARN_MORE' | 'BOOK' | 'ORDER' | 'SHOP' | 'SIGN_UP' | 'CALL';
205
+
206
+ export type HashtagCheckResponse = {
207
+ hashtags?: Array<HashtagInfo>;
208
+ };
209
+
210
+ export type HashtagInfo = {
211
+ hashtag?: string;
212
+ status?: 'safe' | 'banned' | 'restricted' | 'unknown';
213
+ postCount?: number;
214
+ };
215
+
216
+ export type status = 'safe' | 'banned' | 'restricted' | 'unknown';
217
+
218
+ /**
219
+ * Constraints:
220
+ * - Feed posts require images with aspect ratio between 0.8 (4:5 portrait) and 1.91 (1.91:1 landscape).
221
+ * - Images outside this range (e.g., 9:16 Stories/TikTok format) must use contentType 'story'.
222
+ * - Validation happens at post creation; invalid images are rejected immediately with helpful error messages.
223
+ * - Carousels support up to 10 media items.
224
+ * - Stories require media; no captions are published with Stories.
225
+ * - User tags: coordinates range from 0.0 to 1.0 representing position from top-left corner. Tagged users receive notifications.
226
+ *
227
+ * **Automatic Compression (similar to Bluesky):**
228
+ * - All images (story, post, carousel, thumbnails) exceeding 8 MB are automatically compressed using quality reduction and resizing.
229
+ * - Story videos exceeding 100 MB are automatically compressed.
230
+ * - Reel videos exceeding 300 MB are automatically compressed.
231
+ * - Compression uses Sharp (images) and FFmpeg (videos) to maintain quality while meeting size limits.
232
+ * - Original files are preserved; compressed versions are uploaded to blob storage automatically.
233
+ *
234
+ */
235
+ export type InstagramPlatformData = {
236
+ /**
237
+ * Set to 'story' to publish as a Story. Default posts become Reels or feed depending on media.
238
+ */
239
+ contentType?: 'story';
240
+ /**
241
+ * For Reels only. When true (default), the Reel appears on both the Reels tab and your main profile feed. Set to false to post to the Reels tab only.
242
+ */
243
+ shareToFeed?: boolean;
244
+ /**
245
+ * Up to 3 Instagram usernames to invite as collaborators (feed/Reels only)
246
+ */
247
+ collaborators?: Array<(string)>;
248
+ /**
249
+ * Optional first comment to add after the post is created (not applied to Stories)
250
+ */
251
+ firstComment?: string;
252
+ /**
253
+ * Trial Reels configuration. Trial reels are only shared to non-followers initially.
254
+ * They can later be "graduated" (converted to regular reels visible to followers)
255
+ * either manually in the Instagram app or automatically based on performance.
256
+ * Only applies to Reels (video posts).
257
+ *
258
+ */
259
+ trialParams?: {
260
+ /**
261
+ * The graduation strategy specifies when a trial reel becomes a regular reel:
262
+ * - MANUAL: The trial reel can only be manually graduated from the native Instagram app.
263
+ * - SS_PERFORMANCE: The trial reel will be automatically graduated if it performs well with non-followers.
264
+ *
265
+ */
266
+ graduationStrategy?: 'MANUAL' | 'SS_PERFORMANCE';
267
+ };
268
+ /**
269
+ * Tag Instagram users in photos by username and position coordinates. Only works for single image posts and the first image of carousel posts. Not supported for stories or videos.
270
+ */
271
+ userTags?: Array<{
272
+ /**
273
+ * Instagram username (@ symbol is optional and will be removed automatically)
274
+ */
275
+ username: string;
276
+ /**
277
+ * X coordinate position from left edge (0.0 = left, 0.5 = center, 1.0 = right)
278
+ */
279
+ x: number;
280
+ /**
281
+ * Y coordinate position from top edge (0.0 = top, 0.5 = center, 1.0 = bottom)
282
+ */
283
+ y: number;
284
+ }>;
285
+ /**
286
+ * Custom name for the original audio in Reels. Replaces the default "Original Audio" label.
287
+ * Only applies to Reels (video posts). Can only be set once - either during creation or
288
+ * later from the Instagram audio page in the app.
289
+ *
290
+ */
291
+ audioName?: string;
292
+ };
293
+
294
+ /**
295
+ * The graduation strategy specifies when a trial reel becomes a regular reel:
296
+ * - MANUAL: The trial reel can only be manually graduated from the native Instagram app.
297
+ * - SS_PERFORMANCE: The trial reel will be automatically graduated if it performs well with non-followers.
298
+ *
299
+ */
300
+ export type graduationStrategy = 'MANUAL' | 'SS_PERFORMANCE';
301
+
302
+ /**
303
+ * Response for DAILY aggregation (time series breakdown)
304
+ */
305
+ export type LinkedInAggregateAnalyticsDailyResponse = {
306
+ accountId?: string;
307
+ platform?: string;
308
+ accountType?: string;
309
+ username?: string;
310
+ aggregation?: 'DAILY';
311
+ dateRange?: {
312
+ startDate?: string;
313
+ endDate?: string;
314
+ } | null;
315
+ /**
316
+ * Daily breakdown of each metric. Each metric contains an array of date/count pairs.
317
+ * Note: 'reach' (MEMBERS_REACHED) is not available with DAILY aggregation per LinkedIn API limitations.
318
+ *
319
+ */
320
+ analytics?: {
321
+ impressions?: Array<{
322
+ date?: string;
323
+ count?: number;
324
+ }>;
325
+ reactions?: Array<{
326
+ date?: string;
327
+ count?: number;
328
+ }>;
329
+ comments?: Array<{
330
+ date?: string;
331
+ count?: number;
332
+ }>;
333
+ shares?: Array<{
334
+ date?: string;
335
+ count?: number;
336
+ }>;
337
+ };
338
+ /**
339
+ * Metrics that were skipped due to API limitations
340
+ */
341
+ skippedMetrics?: Array<(string)>;
342
+ note?: string;
343
+ lastUpdated?: string;
344
+ };
345
+
346
+ export type aggregation2 = 'DAILY';
347
+
348
+ /**
349
+ * Response for TOTAL aggregation (lifetime totals)
350
+ */
351
+ export type LinkedInAggregateAnalyticsTotalResponse = {
352
+ accountId?: string;
353
+ platform?: string;
354
+ accountType?: string;
355
+ username?: string;
356
+ aggregation?: 'TOTAL';
357
+ dateRange?: {
358
+ startDate?: string;
359
+ endDate?: string;
360
+ } | null;
361
+ analytics?: {
362
+ /**
363
+ * Total impressions across all posts
364
+ */
365
+ impressions?: number;
366
+ /**
367
+ * Unique members reached across all posts
368
+ */
369
+ reach?: number;
370
+ /**
371
+ * Total reactions across all posts
372
+ */
373
+ reactions?: number;
374
+ /**
375
+ * Total comments across all posts
376
+ */
377
+ comments?: number;
378
+ /**
379
+ * Total reshares across all posts
380
+ */
381
+ shares?: number;
382
+ /**
383
+ * Overall engagement rate as percentage
384
+ */
385
+ engagementRate?: number;
386
+ };
387
+ note?: string;
388
+ lastUpdated?: string;
389
+ };
390
+
391
+ export type aggregation3 = 'TOTAL';
392
+
393
+ /**
394
+ * Constraints:
395
+ * - Multi-image posts support up to 20 images.
396
+ * - Multi-video posts are not supported.
397
+ * - Single PDF document posts are supported (max 100MB, ~300 pages). Documents cannot be mixed with other media.
398
+ * - Post ID is returned in the x-restli-id response header.
399
+ * - Link previews are automatically generated for URLs when no media is attached (can be disabled with disableLinkPreview).
400
+ *
401
+ */
402
+ export type LinkedInPlatformData = {
403
+ /**
404
+ * Optional first comment to add after the post is created
405
+ */
406
+ firstComment?: string;
407
+ /**
408
+ * Set to true to disable automatic link previews for URLs in the post content (default is false)
409
+ */
410
+ disableLinkPreview?: boolean;
411
+ };
412
+
413
+ /**
414
+ * Media referenced in posts. URLs must be publicly reachable over HTTPS by the destination platforms.
415
+ * When using third‑party storage, ensure signed links remain valid until upload completes.
416
+ *
417
+ * **Uploading Media:**
418
+ * Use `POST /v1/media/presign` to get a presigned URL, then upload your file directly to cloud storage.
419
+ * Supports files up to 5GB. See the `/v1/media/presign` endpoint documentation for details.
420
+ *
421
+ * **Automatic Media Compression:**
422
+ * Late automatically compresses media that exceeds platform limits, so you don't need to worry about file size restrictions. Compression happens server-side during publishing.
423
+ *
424
+ * **Image compression by platform:**
425
+ * - Twitter/X: >5 MB
426
+ * - Instagram: >8 MB
427
+ * - Threads: >8 MB
428
+ * - Facebook: >10 MB
429
+ * - LinkedIn: >8 MB
430
+ * - TikTok: >20 MB
431
+ * - Pinterest: >32 MB
432
+ * - Reddit: >20 MB
433
+ * - Snapchat: >20 MB
434
+ * - Telegram: >10 MB
435
+ * - Bluesky: >1 MB
436
+ * - YouTube (thumbnails): >2 MB
437
+ * - Google Business: >5 MB
438
+ *
439
+ * **Video compression by platform:**
440
+ * - Twitter/X: >512 MB
441
+ * - Instagram Stories: >100 MB
442
+ * - Instagram Reels: >300 MB
443
+ * - Facebook: >4 GB
444
+ * - LinkedIn: >5 GB
445
+ * - TikTok: >4 GB
446
+ * - Pinterest: >2 GB
447
+ * - Snapchat: >500 MB
448
+ * - Telegram: >50 MB
449
+ *
450
+ * Note: Videos larger than 200 MB may not be compressed due to server timeout constraints. For best results, compress very large videos before uploading.
451
+ *
452
+ */
453
+ export type MediaItem = {
454
+ type?: 'image' | 'video' | 'gif' | 'document';
455
+ url?: string;
456
+ filename?: string;
457
+ /**
458
+ * Optional file size in bytes
459
+ */
460
+ size?: number;
461
+ /**
462
+ * Optional MIME type (e.g. image/jpeg, video/mp4)
463
+ */
464
+ mimeType?: string;
465
+ /**
466
+ * Optional thumbnail image URL for videos
467
+ */
468
+ thumbnail?: string;
469
+ /**
470
+ * Optional custom cover image URL for Instagram Reels
471
+ */
472
+ instagramThumbnail?: string;
473
+ /**
474
+ * Internal flag indicating the image was resized for TikTok
475
+ */
476
+ tiktokProcessed?: boolean;
477
+ };
478
+
479
+ export type type2 = 'image' | 'video' | 'gif' | 'document';
480
+
481
+ export type MediaUploadResponse = {
482
+ files?: Array<UploadedFile>;
483
+ };
484
+
485
+ export type Pagination = {
486
+ page?: number;
487
+ limit?: number;
488
+ total?: number;
489
+ pages?: number;
490
+ };
491
+
492
+ /**
493
+ * Page size
494
+ */
495
+ export type ParameterLimitParam = number;
496
+
497
+ /**
498
+ * Page number (1-based)
499
+ */
500
+ export type ParameterPageParam = number;
501
+
502
+ export type PinterestPlatformData = {
503
+ /**
504
+ * Pin title. Defaults to first line of content or "Pin". Must be ≤ 100 characters.
505
+ */
506
+ title?: string;
507
+ /**
508
+ * Target Pinterest board ID. If omitted, the first available board is used.
509
+ */
510
+ boardId?: string;
511
+ /**
512
+ * Destination link (pin URL)
513
+ */
514
+ link?: string;
515
+ /**
516
+ * Optional cover image for video pins
517
+ */
518
+ coverImageUrl?: string;
519
+ /**
520
+ * Optional key frame time in seconds for derived video cover
521
+ */
522
+ coverImageKeyFrameTime?: number;
523
+ };
524
+
525
+ export type PlatformAnalytics = {
526
+ platform?: string;
527
+ status?: string;
528
+ accountId?: string;
529
+ accountUsername?: string;
530
+ analytics?: PostAnalytics;
531
+ accountMetrics?: {
532
+ /**
533
+ * Followers/fans count (e.g., Instagram, Facebook Pages, Twitter)
534
+ */
535
+ followers?: (number) | null;
536
+ /**
537
+ * Subscribers count (e.g., YouTube)
538
+ */
539
+ subscribers?: (number) | null;
540
+ lastUpdated?: (string) | null;
541
+ } | null;
542
+ };
543
+
544
+ export type PlatformTarget = {
545
+ /**
546
+ * Supported values: twitter, threads, instagram, youtube, facebook, linkedin, pinterest, reddit, tiktok, bluesky, googlebusiness, telegram
547
+ */
548
+ platform?: string;
549
+ accountId?: (string | SocialAccount);
550
+ customContent?: string;
551
+ customMedia?: Array<MediaItem>;
552
+ /**
553
+ * Optional per-platform scheduled time override (uses post.scheduledFor when omitted)
554
+ */
555
+ scheduledFor?: string;
556
+ /**
557
+ * Platform-specific overrides and options.
558
+ */
559
+ platformSpecificData?: (TwitterPlatformData | ThreadsPlatformData | FacebookPlatformData | InstagramPlatformData | LinkedInPlatformData | PinterestPlatformData | YouTubePlatformData | GoogleBusinessPlatformData | TikTokPlatformData | TelegramPlatformData | SnapchatPlatformData);
560
+ /**
561
+ * Platform-specific status: pending, publishing, published, failed
562
+ */
563
+ status?: string;
564
+ /**
565
+ * The native post ID on the platform (populated after successful publish)
566
+ */
567
+ platformPostId?: string;
568
+ /**
569
+ * Public URL of the published post on the platform.
570
+ * Populated after successful publish. For immediate posts (publishNow=true),
571
+ * this is included in the response. For scheduled posts, fetch the post
572
+ * via GET /v1/posts/{postId} after the scheduled time.
573
+ *
574
+ */
575
+ platformPostUrl?: string;
576
+ /**
577
+ * Timestamp when the post was published to this platform
578
+ */
579
+ publishedAt?: string;
580
+ };
581
+
582
+ export type Post = {
583
+ _id?: string;
584
+ userId?: (string | User);
585
+ /**
586
+ * YouTube: title must be ≤ 100 characters.
587
+ *
588
+ */
589
+ title?: string;
590
+ content?: string;
591
+ mediaItems?: Array<MediaItem>;
592
+ platforms?: Array<PlatformTarget>;
593
+ scheduledFor?: string;
594
+ timezone?: string;
595
+ status?: 'draft' | 'scheduled' | 'publishing' | 'published' | 'failed' | 'partial';
596
+ /**
597
+ * YouTube tag constraints when targeting YouTube:
598
+ * - No count cap; duplicates removed.
599
+ * - Each tag must be ≤ 100 chars.
600
+ * - Combined characters across all tags ≤ 500.
601
+ *
602
+ */
603
+ tags?: Array<(string)>;
604
+ hashtags?: Array<(string)>;
605
+ mentions?: Array<(string)>;
606
+ visibility?: 'public' | 'private' | 'unlisted';
607
+ metadata?: {
608
+ [key: string]: unknown;
609
+ };
610
+ /**
611
+ * Profile ID if the post was scheduled via the queue
612
+ */
613
+ queuedFromProfile?: string;
614
+ /**
615
+ * Queue ID if the post was scheduled via a specific queue
616
+ */
617
+ queueId?: string;
618
+ createdAt?: string;
619
+ updatedAt?: string;
620
+ };
621
+
622
+ export type status2 = 'draft' | 'scheduled' | 'publishing' | 'published' | 'failed' | 'partial';
623
+
624
+ export type visibility = 'public' | 'private' | 'unlisted';
625
+
626
+ export type PostAnalytics = {
627
+ impressions?: number;
628
+ reach?: number;
629
+ likes?: number;
630
+ comments?: number;
631
+ shares?: number;
632
+ clicks?: number;
633
+ views?: number;
634
+ engagementRate?: number;
635
+ lastUpdated?: string;
636
+ };
637
+
638
+ export type PostCreateResponse = {
639
+ message?: string;
640
+ post?: Post;
641
+ };
642
+
643
+ export type PostDeleteResponse = {
644
+ message?: string;
645
+ };
646
+
647
+ export type PostGetResponse = {
648
+ post?: Post;
649
+ };
650
+
651
+ /**
652
+ * Publishing log entry showing details of a post publishing attempt
653
+ */
654
+ export type PostLog = {
655
+ _id?: string;
656
+ postId?: (string | {
657
+ _id?: string;
658
+ content?: string;
659
+ status?: string;
660
+ });
661
+ userId?: string;
662
+ profileId?: string;
663
+ platform?: 'tiktok' | 'instagram' | 'facebook' | 'youtube' | 'linkedin' | 'twitter' | 'threads' | 'pinterest' | 'reddit' | 'bluesky' | 'googlebusiness' | 'telegram' | 'snapchat';
664
+ accountId?: string;
665
+ accountUsername?: string;
666
+ /**
667
+ * Type of action logged:
668
+ * - `publish` - Initial publish attempt
669
+ * - `retry` - Retry after failure
670
+ * - `media_upload` - Media upload step
671
+ * - `rate_limit_pause` - Account paused due to rate limits
672
+ * - `token_refresh` - Token was refreshed
673
+ * - `cancelled` - Post was cancelled
674
+ *
675
+ */
676
+ action?: 'publish' | 'retry' | 'media_upload' | 'rate_limit_pause' | 'token_refresh' | 'cancelled';
677
+ status?: 'success' | 'failed' | 'pending' | 'skipped';
678
+ /**
679
+ * HTTP status code from platform API
680
+ */
681
+ statusCode?: number;
682
+ /**
683
+ * Platform API endpoint called
684
+ */
685
+ endpoint?: string;
686
+ request?: {
687
+ /**
688
+ * First 200 chars of caption
689
+ */
690
+ contentPreview?: string;
691
+ mediaCount?: number;
692
+ mediaTypes?: Array<(string)>;
693
+ /**
694
+ * URLs of media items sent to platform
695
+ */
696
+ mediaUrls?: Array<(string)>;
697
+ scheduledFor?: string;
698
+ /**
699
+ * Full request body JSON (max 5000 chars)
700
+ */
701
+ rawBody?: string;
702
+ };
703
+ response?: {
704
+ /**
705
+ * ID returned by platform on success
706
+ */
707
+ platformPostId?: string;
708
+ /**
709
+ * URL of published post
710
+ */
711
+ platformPostUrl?: string;
712
+ /**
713
+ * Error message on failure
714
+ */
715
+ errorMessage?: string;
716
+ /**
717
+ * Platform-specific error code
718
+ */
719
+ errorCode?: string;
720
+ /**
721
+ * Full response body JSON (max 5000 chars)
722
+ */
723
+ rawBody?: string;
724
+ };
725
+ /**
726
+ * How long the operation took in milliseconds
727
+ */
728
+ durationMs?: number;
729
+ /**
730
+ * Attempt number (1 for first try, 2+ for retries)
731
+ */
732
+ attemptNumber?: number;
733
+ createdAt?: string;
734
+ };
735
+
736
+ export type platform = 'tiktok' | 'instagram' | 'facebook' | 'youtube' | 'linkedin' | 'twitter' | 'threads' | 'pinterest' | 'reddit' | 'bluesky' | 'googlebusiness' | 'telegram' | 'snapchat';
737
+
738
+ /**
739
+ * Type of action logged:
740
+ * - `publish` - Initial publish attempt
741
+ * - `retry` - Retry after failure
742
+ * - `media_upload` - Media upload step
743
+ * - `rate_limit_pause` - Account paused due to rate limits
744
+ * - `token_refresh` - Token was refreshed
745
+ * - `cancelled` - Post was cancelled
746
+ *
747
+ */
748
+ export type action = 'publish' | 'retry' | 'media_upload' | 'rate_limit_pause' | 'token_refresh' | 'cancelled';
749
+
750
+ export type status3 = 'success' | 'failed' | 'pending' | 'skipped';
751
+
752
+ export type PostLogDetail = PostLog & {
753
+ /**
754
+ * Populated post with full details
755
+ */
756
+ postId?: {
757
+ _id?: string;
758
+ content?: string;
759
+ status?: string;
760
+ scheduledFor?: string;
761
+ platforms?: Array<{
762
+ [key: string]: unknown;
763
+ }>;
764
+ mediaItems?: Array<{
765
+ [key: string]: unknown;
766
+ }>;
767
+ };
768
+ /**
769
+ * Populated account reference
770
+ */
771
+ accountId?: {
772
+ _id?: string;
773
+ platform?: string;
774
+ username?: string;
775
+ displayName?: string;
776
+ };
777
+ /**
778
+ * Additional metadata (e.g., rate limit info)
779
+ */
780
+ metadata?: {
781
+ [key: string]: unknown;
782
+ };
783
+ };
784
+
785
+ export type PostRetryResponse = {
786
+ message?: string;
787
+ post?: Post;
788
+ };
789
+
790
+ export type PostsListResponse = {
791
+ posts?: Array<Post>;
792
+ pagination?: Pagination;
793
+ };
794
+
795
+ export type PostUpdateResponse = {
796
+ message?: string;
797
+ post?: Post;
798
+ };
799
+
800
+ export type Profile = {
801
+ _id?: string;
802
+ userId?: string;
803
+ name?: string;
804
+ description?: string;
805
+ color?: string;
806
+ isDefault?: boolean;
807
+ /**
808
+ * Only present when `includeOverLimit=true` is used. Indicates if this profile
809
+ * exceeds the user's plan limit. Over-limit profiles cannot be used for posting
810
+ * but can be managed (disconnected accounts, deleted).
811
+ *
812
+ */
813
+ isOverLimit?: boolean;
814
+ createdAt?: string;
815
+ };
816
+
817
+ export type ProfileCreateResponse = {
818
+ message?: string;
819
+ profile?: Profile;
820
+ };
821
+
822
+ export type ProfileDeleteResponse = {
823
+ message?: string;
824
+ };
825
+
826
+ export type ProfileGetResponse = {
827
+ profile?: Profile;
828
+ };
829
+
830
+ export type ProfilesListResponse = {
831
+ profiles?: Array<Profile>;
832
+ };
833
+
834
+ export type ProfileUpdateResponse = {
835
+ message?: string;
836
+ profile?: Profile;
837
+ };
838
+
839
+ export type QueueDeleteResponse = {
840
+ success?: boolean;
841
+ deleted?: boolean;
842
+ };
843
+
844
+ export type QueueNextSlotResponse = {
845
+ profileId?: string;
846
+ nextSlot?: string;
847
+ timezone?: string;
848
+ };
849
+
850
+ export type QueuePreviewResponse = {
851
+ profileId?: string;
852
+ count?: number;
853
+ slots?: Array<(string)>;
854
+ };
855
+
856
+ export type QueueSchedule = {
857
+ /**
858
+ * Unique queue identifier
859
+ */
860
+ _id?: string;
861
+ /**
862
+ * Profile ID this queue belongs to
863
+ */
864
+ profileId?: string;
865
+ /**
866
+ * Queue name (e.g., "Morning Posts", "Evening Content")
867
+ */
868
+ name?: string;
869
+ /**
870
+ * IANA timezone (e.g., America/New_York)
871
+ */
872
+ timezone?: string;
873
+ slots?: Array<QueueSlot>;
874
+ /**
875
+ * Whether the queue is active
876
+ */
877
+ active?: boolean;
878
+ /**
879
+ * Whether this is the default queue for the profile (used when no queueId specified)
880
+ */
881
+ isDefault?: boolean;
882
+ createdAt?: string;
883
+ updatedAt?: string;
884
+ };
885
+
886
+ export type QueueSlot = {
887
+ /**
888
+ * Day of week (0=Sunday, 6=Saturday)
889
+ */
890
+ dayOfWeek?: number;
891
+ /**
892
+ * Time in HH:mm format (24-hour)
893
+ */
894
+ time?: string;
895
+ };
896
+
897
+ export type QueueSlotsResponse = {
898
+ exists?: boolean;
899
+ schedule?: QueueSchedule;
900
+ nextSlots?: Array<(string)>;
901
+ };
902
+
903
+ export type QueueUpdateResponse = {
904
+ success?: boolean;
905
+ schedule?: QueueSchedule;
906
+ nextSlots?: Array<(string)>;
907
+ reshuffledCount?: number;
908
+ };
909
+
910
+ /**
911
+ * Snapchat Public Profile API constraints:
912
+ *
913
+ * **General Requirements:**
914
+ * - Snapchat requires a Public Profile to publish content
915
+ * - Media is required for all content types (no text-only posts)
916
+ * - Only one media item per post is supported
917
+ * - Media is automatically encrypted using AES-256-CBC before upload
918
+ *
919
+ * **Content Types:**
920
+ * - **Story** (default): Ephemeral content visible for 24 hours. No caption/text supported.
921
+ * - **Saved Story**: Permanent story on your Public Profile. Uses post content as title (max 45 chars).
922
+ * - **Spotlight**: Video content for Snapchat's entertainment feed. Supports description (max 160 chars) with hashtags.
923
+ *
924
+ * **Media Constraints:**
925
+ * - Images: max 20 MB, JPEG/PNG format
926
+ * - Videos: max 500 MB, MP4 format, 5-60 seconds duration, minimum 540x960px resolution
927
+ * - Aspect ratio: 9:16 recommended
928
+ *
929
+ * **Analytics:**
930
+ * - Views, screenshots, shares, unique viewers, completion rate available
931
+ * - Analytics are fetched per content type (story/saved_story/spotlight)
932
+ *
933
+ */
934
+ export type SnapchatPlatformData = {
935
+ /**
936
+ * Type of Snapchat content to publish:
937
+ * - `story` - Ephemeral snap visible for 24 hours (default)
938
+ * - `saved_story` - Permanent story saved to Public Profile
939
+ * - `spotlight` - Video posted to Spotlight (Snapchat's TikTok-like feed)
940
+ *
941
+ */
942
+ contentType?: 'story' | 'saved_story' | 'spotlight';
943
+ };
944
+
945
+ /**
946
+ * Type of Snapchat content to publish:
947
+ * - `story` - Ephemeral snap visible for 24 hours (default)
948
+ * - `saved_story` - Permanent story saved to Public Profile
949
+ * - `spotlight` - Video posted to Spotlight (Snapchat's TikTok-like feed)
950
+ *
951
+ */
952
+ export type contentType2 = 'story' | 'saved_story' | 'spotlight';
953
+
954
+ export type SocialAccount = {
955
+ _id?: string;
956
+ platform?: string;
957
+ profileId?: (string | Profile);
958
+ username?: string;
959
+ displayName?: string;
960
+ /**
961
+ * Full profile URL for the connected account. Available for all platforms:
962
+ * - Twitter/X: https://x.com/{username}
963
+ * - Instagram: https://instagram.com/{username}
964
+ * - TikTok: https://tiktok.com/@{username}
965
+ * - YouTube: https://youtube.com/@{handle} or https://youtube.com/channel/{id}
966
+ * - LinkedIn Personal: https://www.linkedin.com/in/{vanityName}/
967
+ * - LinkedIn Organization: https://www.linkedin.com/company/{vanityName}/
968
+ * - Threads: https://threads.net/@{username}
969
+ * - Pinterest: https://pinterest.com/{username}
970
+ * - Reddit: https://reddit.com/user/{username}
971
+ * - Bluesky: https://bsky.app/profile/{handle}
972
+ * - Facebook: https://facebook.com/{username} or https://facebook.com/{pageId}
973
+ * - Google Business: Google Maps URL for the business location
974
+ *
975
+ */
976
+ profileUrl?: string;
977
+ isActive?: boolean;
978
+ /**
979
+ * Follower count (only included if user has analytics add-on)
980
+ */
981
+ followersCount?: number;
982
+ /**
983
+ * Last time follower count was updated (only included if user has analytics add-on)
984
+ */
985
+ followersLastUpdated?: string;
986
+ };
987
+
988
+ /**
989
+ * Telegram channel/group posting settings:
990
+ * - Supports text, images (up to 10), videos (up to 10), and mixed media albums
991
+ * - Posts to channels display the channel name and logo as author
992
+ * - Posts to groups display the bot name (Late) as author
993
+ * - Message IDs are returned for analytics tracking
994
+ * - Captions support up to 1024 characters for media posts, 4096 for text-only
995
+ *
996
+ * **Analytics:**
997
+ * - **Not available via API.** The Telegram Bot API does not expose message analytics (views, forwards, reactions).
998
+ * - View counts are only visible to channel admins directly in the Telegram app.
999
+ * - This is a Telegram platform limitation that affects all third-party tools.
1000
+ *
1001
+ */
1002
+ export type TelegramPlatformData = {
1003
+ /**
1004
+ * Text formatting mode for the message (default is HTML)
1005
+ */
1006
+ parseMode?: 'HTML' | 'Markdown' | 'MarkdownV2';
1007
+ /**
1008
+ * Disable link preview generation for URLs in the message
1009
+ */
1010
+ disableWebPagePreview?: boolean;
1011
+ /**
1012
+ * Send the message silently (users will receive notification without sound)
1013
+ */
1014
+ disableNotification?: boolean;
1015
+ /**
1016
+ * Protect message content from forwarding and saving
1017
+ */
1018
+ protectContent?: boolean;
1019
+ };
1020
+
1021
+ /**
1022
+ * Text formatting mode for the message (default is HTML)
1023
+ */
1024
+ export type parseMode = 'HTML' | 'Markdown' | 'MarkdownV2';
1025
+
1026
+ /**
1027
+ * Constraints:
1028
+ * - Carousel posts support up to 10 images (no videos in carousels).
1029
+ * - Single posts support one image or one video.
1030
+ * - Videos must be H.264/AAC MP4 format, max 5 minutes duration.
1031
+ * - Images must be JPEG or PNG, max 8 MB each.
1032
+ * - threadItems creates a reply chain (Threads equivalent of Twitter threads).
1033
+ *
1034
+ */
1035
+ export type ThreadsPlatformData = {
1036
+ /**
1037
+ * Sequence of posts in a Threads thread (root then replies in order).
1038
+ */
1039
+ threadItems?: Array<{
1040
+ content?: string;
1041
+ mediaItems?: Array<MediaItem>;
1042
+ }>;
1043
+ };
1044
+
1045
+ /**
1046
+ * TikTok platform-specific settings for video/photo posting.
1047
+ *
1048
+ * **Constraints:**
1049
+ * - Photo carousels support up to 35 images.
1050
+ * - **Title length limits**:
1051
+ * - Videos: up to 2200 chars (full content used as title)
1052
+ * - Photos: content is automatically truncated to 90 chars for title (hashtags/URLs stripped). Use 'description' field for longer text (up to 4000 chars).
1053
+ * - privacyLevel must be chosen from creator_info.privacy_level_options (no defaulting).
1054
+ * - allowDuet and allowStitch required for videos; allowComment for all.
1055
+ * - contentPreviewConfirmed and expressConsentGiven must be true before posting.
1056
+ *
1057
+ * **Note:** Both camelCase and snake_case field names are accepted for backwards compatibility.
1058
+ * The nested `tiktokSettings` object format is also still supported but deprecated.
1059
+ *
1060
+ */
1061
+ export type TikTokPlatformData = {
1062
+ /**
1063
+ * When true, Late sends the post to the TikTok Creator Inbox as a draft instead of publishing it immediately. When omitted or false, TikTok uses direct posting (live publish) as usual.
1064
+ *
1065
+ */
1066
+ draft?: boolean;
1067
+ /**
1068
+ * One of the values returned by the TikTok creator info API for the account
1069
+ */
1070
+ privacyLevel?: string;
1071
+ /**
1072
+ * Allow comments on the post
1073
+ */
1074
+ allowComment?: boolean;
1075
+ /**
1076
+ * Allow duets (required for video posts)
1077
+ */
1078
+ allowDuet?: boolean;
1079
+ /**
1080
+ * Allow stitches (required for video posts)
1081
+ */
1082
+ allowStitch?: boolean;
1083
+ /**
1084
+ * Type of commercial content disclosure
1085
+ */
1086
+ commercialContentType?: 'none' | 'brand_organic' | 'brand_content';
1087
+ /**
1088
+ * Whether the post promotes a brand partner
1089
+ */
1090
+ brandPartnerPromote?: boolean;
1091
+ /**
1092
+ * Whether the post is a brand organic post
1093
+ */
1094
+ isBrandOrganicPost?: boolean;
1095
+ /**
1096
+ * User has confirmed they previewed the content
1097
+ */
1098
+ contentPreviewConfirmed?: boolean;
1099
+ /**
1100
+ * User has given express consent for posting
1101
+ */
1102
+ expressConsentGiven?: boolean;
1103
+ /**
1104
+ * Optional override. Defaults based on provided media items.
1105
+ */
1106
+ mediaType?: 'video' | 'photo';
1107
+ /**
1108
+ * Optional for video posts. Timestamp in milliseconds to select which frame to use as thumbnail (defaults to 1000ms/1 second).
1109
+ */
1110
+ videoCoverTimestampMs?: number;
1111
+ /**
1112
+ * Optional for photo carousels. Index of image to use as cover, 0-based (defaults to 0/first image).
1113
+ */
1114
+ photoCoverIndex?: number;
1115
+ /**
1116
+ * When true, TikTok may add recommended music (photos only)
1117
+ */
1118
+ autoAddMusic?: boolean;
1119
+ /**
1120
+ * Set true to disclose AI-generated content
1121
+ */
1122
+ videoMadeWithAi?: boolean;
1123
+ /**
1124
+ * Optional long-form description for photo posts (max 4000 chars).
1125
+ * Recommended for photo posts when content exceeds 90 characters, as photo titles are automatically truncated to 90 chars (after stripping hashtags/URLs).
1126
+ *
1127
+ */
1128
+ description?: string;
1129
+ };
1130
+
1131
+ /**
1132
+ * Type of commercial content disclosure
1133
+ */
1134
+ export type commercialContentType = 'none' | 'brand_organic' | 'brand_content';
1135
+
1136
+ /**
1137
+ * Optional override. Defaults based on provided media items.
1138
+ */
1139
+ export type mediaType = 'video' | 'photo';
1140
+
1141
+ /**
1142
+ * **DEPRECATED**: Use flat properties directly in TikTokPlatformData instead.
1143
+ * This nested format is supported for backwards compatibility only.
1144
+ *
1145
+ * @deprecated
1146
+ */
1147
+ export type TikTokSettings = {
1148
+ privacyLevel?: string;
1149
+ allowComment?: boolean;
1150
+ allowDuet?: boolean;
1151
+ allowStitch?: boolean;
1152
+ commercialContentType?: string;
1153
+ brandPartnerPromote?: boolean;
1154
+ isBrandOrganicPost?: boolean;
1155
+ contentPreviewConfirmed?: boolean;
1156
+ expressConsentGiven?: boolean;
1157
+ mediaType?: string;
1158
+ videoCoverTimestampMs?: number;
1159
+ photoCoverIndex?: number;
1160
+ autoAddMusic?: boolean;
1161
+ videoMadeWithAi?: boolean;
1162
+ description?: string;
1163
+ };
1164
+
1165
+ export type TranscriptResponse = {
1166
+ transcript?: string;
1167
+ segments?: Array<TranscriptSegment>;
1168
+ language?: string;
1169
+ };
1170
+
1171
+ export type TranscriptSegment = {
1172
+ text?: string;
1173
+ start?: number;
1174
+ duration?: number;
1175
+ };
1176
+
1177
+ export type TwitterPlatformData = {
1178
+ /**
1179
+ * Sequence of tweets in a thread. First item is the root tweet.
1180
+ */
1181
+ threadItems?: Array<{
1182
+ content?: string;
1183
+ mediaItems?: Array<MediaItem>;
1184
+ }>;
1185
+ };
1186
+
1187
+ export type UploadedFile = {
1188
+ type?: 'image' | 'video' | 'document';
1189
+ url?: string;
1190
+ filename?: string;
1191
+ size?: number;
1192
+ mimeType?: string;
1193
+ };
1194
+
1195
+ export type type3 = 'image' | 'video' | 'document';
1196
+
1197
+ export type UploadTokenResponse = {
1198
+ token?: string;
1199
+ uploadUrl?: string;
1200
+ expiresAt?: string;
1201
+ status?: 'pending' | 'completed' | 'expired';
1202
+ };
1203
+
1204
+ export type status4 = 'pending' | 'completed' | 'expired';
1205
+
1206
+ export type UploadTokenStatusResponse = {
1207
+ token?: string;
1208
+ status?: 'pending' | 'completed' | 'expired';
1209
+ files?: Array<UploadedFile>;
1210
+ createdAt?: string;
1211
+ expiresAt?: string;
1212
+ completedAt?: string;
1213
+ };
1214
+
1215
+ export type UsageStats = {
1216
+ planName?: string;
1217
+ billingPeriod?: 'monthly' | 'yearly';
1218
+ signupDate?: string;
1219
+ limits?: {
1220
+ uploads?: number;
1221
+ profiles?: number;
1222
+ };
1223
+ usage?: {
1224
+ uploads?: number;
1225
+ profiles?: number;
1226
+ lastReset?: string;
1227
+ };
1228
+ };
1229
+
1230
+ export type billingPeriod = 'monthly' | 'yearly';
1231
+
1232
+ export type User = {
1233
+ _id?: string;
1234
+ email?: string;
1235
+ name?: string;
1236
+ role?: string;
1237
+ createdAt?: string;
1238
+ };
1239
+
1240
+ export type UserGetResponse = {
1241
+ user?: User;
1242
+ };
1243
+
1244
+ export type UsersListResponse = {
1245
+ users?: Array<User>;
1246
+ };
1247
+
1248
+ /**
1249
+ * Individual webhook configuration for receiving real-time notifications
1250
+ */
1251
+ export type Webhook = {
1252
+ /**
1253
+ * Unique webhook identifier
1254
+ */
1255
+ _id?: string;
1256
+ /**
1257
+ * Webhook name (for identification)
1258
+ */
1259
+ name?: string;
1260
+ /**
1261
+ * Webhook endpoint URL
1262
+ */
1263
+ url?: string;
1264
+ /**
1265
+ * Secret key for HMAC-SHA256 signature (not returned in responses for security)
1266
+ */
1267
+ secret?: string;
1268
+ /**
1269
+ * Events subscribed to
1270
+ */
1271
+ events?: Array<('post.scheduled' | 'post.published' | 'post.failed' | 'post.partial' | 'account.disconnected')>;
1272
+ /**
1273
+ * Whether webhook delivery is enabled
1274
+ */
1275
+ isActive?: boolean;
1276
+ /**
1277
+ * Timestamp of last successful webhook delivery
1278
+ */
1279
+ lastFiredAt?: string;
1280
+ /**
1281
+ * Consecutive delivery failures (resets on success, webhook disabled at 10)
1282
+ */
1283
+ failureCount?: number;
1284
+ /**
1285
+ * Custom headers included in webhook requests
1286
+ */
1287
+ customHeaders?: {
1288
+ [key: string]: (string);
1289
+ };
1290
+ };
1291
+
1292
+ /**
1293
+ * Webhook delivery log entry
1294
+ */
1295
+ export type WebhookLog = {
1296
+ _id?: string;
1297
+ /**
1298
+ * ID of the webhook that was triggered
1299
+ */
1300
+ webhookId?: string;
1301
+ /**
1302
+ * Name of the webhook that was triggered
1303
+ */
1304
+ webhookName?: string;
1305
+ event?: 'post.scheduled' | 'post.published' | 'post.failed' | 'post.partial' | 'account.disconnected' | 'webhook.test';
1306
+ url?: string;
1307
+ status?: 'success' | 'failed';
1308
+ /**
1309
+ * HTTP status code from webhook endpoint
1310
+ */
1311
+ statusCode?: number;
1312
+ /**
1313
+ * Payload sent to webhook endpoint
1314
+ */
1315
+ requestPayload?: {
1316
+ [key: string]: unknown;
1317
+ };
1318
+ /**
1319
+ * Response body from webhook endpoint (truncated to 10KB)
1320
+ */
1321
+ responseBody?: string;
1322
+ /**
1323
+ * Error message if delivery failed
1324
+ */
1325
+ errorMessage?: string;
1326
+ /**
1327
+ * Delivery attempt number (max 3 retries)
1328
+ */
1329
+ attemptNumber?: number;
1330
+ /**
1331
+ * Response time in milliseconds
1332
+ */
1333
+ responseTime?: number;
1334
+ createdAt?: string;
1335
+ };
1336
+
1337
+ export type event = 'post.scheduled' | 'post.published' | 'post.failed' | 'post.partial' | 'account.disconnected' | 'webhook.test';
1338
+
1339
+ export type status5 = 'success' | 'failed';
1340
+
1341
+ /**
1342
+ * Webhook payload for account disconnected events
1343
+ */
1344
+ export type WebhookPayloadAccountDisconnected = {
1345
+ event?: 'account.disconnected';
1346
+ account?: {
1347
+ /**
1348
+ * The account's unique identifier (same as used in /v1/accounts/{accountId})
1349
+ */
1350
+ accountId?: string;
1351
+ /**
1352
+ * The profile's unique identifier this account belongs to
1353
+ */
1354
+ profileId?: string;
1355
+ platform?: string;
1356
+ username?: string;
1357
+ displayName?: string;
1358
+ /**
1359
+ * Whether the disconnection was intentional (user action) or unintentional (token expired/revoked)
1360
+ */
1361
+ disconnectionType?: 'intentional' | 'unintentional';
1362
+ /**
1363
+ * Human-readable reason for the disconnection
1364
+ */
1365
+ reason?: string;
1366
+ };
1367
+ timestamp?: string;
1368
+ };
1369
+
1370
+ export type event2 = 'account.disconnected';
1371
+
1372
+ /**
1373
+ * Whether the disconnection was intentional (user action) or unintentional (token expired/revoked)
1374
+ */
1375
+ export type disconnectionType = 'intentional' | 'unintentional';
1376
+
1377
+ /**
1378
+ * Webhook payload for post events
1379
+ */
1380
+ export type WebhookPayloadPost = {
1381
+ event?: 'post.scheduled' | 'post.published' | 'post.failed' | 'post.partial';
1382
+ post?: {
1383
+ id?: string;
1384
+ content?: string;
1385
+ status?: string;
1386
+ scheduledFor?: string;
1387
+ publishedAt?: string;
1388
+ platforms?: Array<{
1389
+ platform?: string;
1390
+ status?: string;
1391
+ publishedUrl?: string;
1392
+ error?: string;
1393
+ }>;
1394
+ };
1395
+ timestamp?: string;
1396
+ };
1397
+
1398
+ export type event3 = 'post.scheduled' | 'post.published' | 'post.failed' | 'post.partial';
1399
+
1400
+ export type YouTubeDailyViewsResponse = {
1401
+ success?: boolean;
1402
+ /**
1403
+ * The YouTube video ID
1404
+ */
1405
+ videoId?: string;
1406
+ dateRange?: {
1407
+ startDate?: string;
1408
+ endDate?: string;
1409
+ };
1410
+ /**
1411
+ * Sum of views across all days in the range
1412
+ */
1413
+ totalViews?: number;
1414
+ dailyViews?: Array<{
1415
+ date?: string;
1416
+ views?: number;
1417
+ estimatedMinutesWatched?: number;
1418
+ /**
1419
+ * Average view duration in seconds
1420
+ */
1421
+ averageViewDuration?: number;
1422
+ subscribersGained?: number;
1423
+ subscribersLost?: number;
1424
+ likes?: number;
1425
+ comments?: number;
1426
+ shares?: number;
1427
+ }>;
1428
+ /**
1429
+ * When the data was last synced from YouTube
1430
+ */
1431
+ lastSyncedAt?: (string) | null;
1432
+ scopeStatus?: {
1433
+ hasAnalyticsScope?: boolean;
1434
+ };
1435
+ };
1436
+
1437
+ /**
1438
+ * YouTube video upload settings:
1439
+ * - Videos ≤ 3 minutes are automatically detected as YouTube Shorts
1440
+ * - Videos > 3 minutes become regular YouTube videos
1441
+ * - Custom thumbnails supported for regular videos (via mediaItem.thumbnail)
1442
+ * - Custom thumbnails NOT supported for Shorts via API
1443
+ * - Scheduled videos are uploaded immediately as the specified visibility and published at scheduled time
1444
+ * - Visibility defaults to "public" if not specified
1445
+ * - Set containsSyntheticMedia: true if your video contains AI-generated content
1446
+ *
1447
+ */
1448
+ export type YouTubePlatformData = {
1449
+ /**
1450
+ * Video title. Defaults to first line of content or "Untitled Video". Must be ≤ 100 characters.
1451
+ */
1452
+ title?: string;
1453
+ /**
1454
+ * Video visibility setting:
1455
+ * - public: Anyone can search for and watch (default)
1456
+ * - unlisted: Only people with the link can watch
1457
+ * - private: Only you and people you specifically share with can watch
1458
+ *
1459
+ */
1460
+ visibility?: 'public' | 'private' | 'unlisted';
1461
+ /**
1462
+ * Optional first comment to post immediately after video upload. Up to 10,000 characters (YouTube's comment limit).
1463
+ */
1464
+ firstComment?: string;
1465
+ /**
1466
+ * AI-generated content disclosure flag. Set to true if your video contains AI-generated or synthetic content
1467
+ * that could be mistaken for real people, places, or events. This helps viewers understand when realistic
1468
+ * content has been created or altered using AI. YouTube may add a label to videos when this is set.
1469
+ * Added to YouTube Data API in October 2024.
1470
+ *
1471
+ */
1472
+ containsSyntheticMedia?: boolean;
1473
+ };
1474
+
1475
+ export type YouTubeScopeMissingResponse = {
1476
+ success?: boolean;
1477
+ error?: string;
1478
+ code?: string;
1479
+ scopeStatus?: {
1480
+ hasAnalyticsScope?: boolean;
1481
+ requiresReauthorization?: boolean;
1482
+ /**
1483
+ * URL to redirect user for reauthorization
1484
+ */
1485
+ reauthorizeUrl?: string;
1486
+ };
1487
+ };
1488
+
1489
+ export type GetV1ToolsYoutubeDownloadData = {
1490
+ query: {
1491
+ /**
1492
+ * Action to perform: 'download' returns download URL, 'formats' lists available formats
1493
+ */
1494
+ action?: 'download' | 'formats';
1495
+ /**
1496
+ * Desired format (when action=download)
1497
+ */
1498
+ format?: 'video' | 'audio';
1499
+ /**
1500
+ * Specific format ID from formats list
1501
+ */
1502
+ formatId?: string;
1503
+ /**
1504
+ * Desired quality (when action=download)
1505
+ */
1506
+ quality?: 'hd' | 'sd';
1507
+ /**
1508
+ * YouTube video URL or video ID
1509
+ */
1510
+ url: string;
1511
+ };
1512
+ };
1513
+
1514
+ export type GetV1ToolsYoutubeDownloadResponse = ({
1515
+ success?: boolean;
1516
+ title?: string;
1517
+ downloadUrl?: string;
1518
+ formats?: Array<{
1519
+ id?: string;
1520
+ label?: string;
1521
+ ext?: string;
1522
+ type?: string;
1523
+ height?: number;
1524
+ width?: number;
1525
+ }>;
1526
+ });
1527
+
1528
+ export type GetV1ToolsYoutubeDownloadError = ({
1529
+ error?: string;
1530
+ } | unknown);
1531
+
1532
+ export type GetV1ToolsYoutubeTranscriptData = {
1533
+ query: {
1534
+ /**
1535
+ * Language code for transcript
1536
+ */
1537
+ lang?: string;
1538
+ /**
1539
+ * YouTube video URL or video ID
1540
+ */
1541
+ url: string;
1542
+ };
1543
+ };
1544
+
1545
+ export type GetV1ToolsYoutubeTranscriptResponse = ({
1546
+ success?: boolean;
1547
+ videoId?: string;
1548
+ language?: string;
1549
+ fullText?: string;
1550
+ segments?: Array<{
1551
+ text?: string;
1552
+ start?: number;
1553
+ duration?: number;
1554
+ }>;
1555
+ });
1556
+
1557
+ export type GetV1ToolsYoutubeTranscriptError = (unknown);
1558
+
1559
+ export type GetV1ToolsInstagramDownloadData = {
1560
+ query: {
1561
+ /**
1562
+ * Instagram reel or post URL
1563
+ */
1564
+ url: string;
1565
+ };
1566
+ };
1567
+
1568
+ export type GetV1ToolsInstagramDownloadResponse = ({
1569
+ success?: boolean;
1570
+ title?: string;
1571
+ downloadUrl?: string;
1572
+ });
1573
+
1574
+ export type GetV1ToolsInstagramDownloadError = unknown;
1575
+
1576
+ export type PostV1ToolsInstagramHashtagCheckerData = {
1577
+ body: {
1578
+ hashtags: Array<(string)>;
1579
+ };
1580
+ };
1581
+
1582
+ export type PostV1ToolsInstagramHashtagCheckerResponse = ({
1583
+ success?: boolean;
1584
+ results?: Array<{
1585
+ hashtag?: string;
1586
+ status?: 'banned' | 'restricted' | 'safe' | 'unknown';
1587
+ reason?: string;
1588
+ confidence?: number;
1589
+ }>;
1590
+ summary?: {
1591
+ banned?: number;
1592
+ restricted?: number;
1593
+ safe?: number;
1594
+ };
1595
+ });
1596
+
1597
+ export type PostV1ToolsInstagramHashtagCheckerError = unknown;
1598
+
1599
+ export type GetV1ToolsTiktokDownloadData = {
1600
+ query: {
1601
+ /**
1602
+ * 'formats' to list available formats
1603
+ */
1604
+ action?: 'download' | 'formats';
1605
+ /**
1606
+ * Specific format ID (0 = no watermark, etc.)
1607
+ */
1608
+ formatId?: string;
1609
+ /**
1610
+ * TikTok video URL or ID
1611
+ */
1612
+ url: string;
1613
+ };
1614
+ };
1615
+
1616
+ export type GetV1ToolsTiktokDownloadResponse = ({
1617
+ success?: boolean;
1618
+ title?: string;
1619
+ downloadUrl?: string;
1620
+ formats?: Array<{
1621
+ id?: string;
1622
+ label?: string;
1623
+ ext?: string;
1624
+ }>;
1625
+ });
1626
+
1627
+ export type GetV1ToolsTiktokDownloadError = unknown;
1628
+
1629
+ export type GetV1ToolsTwitterDownloadData = {
1630
+ query: {
1631
+ action?: 'download' | 'formats';
1632
+ formatId?: string;
1633
+ /**
1634
+ * Twitter/X post URL
1635
+ */
1636
+ url: string;
1637
+ };
1638
+ };
1639
+
1640
+ export type GetV1ToolsTwitterDownloadResponse = ({
1641
+ success?: boolean;
1642
+ title?: string;
1643
+ downloadUrl?: string;
1644
+ });
1645
+
1646
+ export type GetV1ToolsTwitterDownloadError = unknown;
1647
+
1648
+ export type GetV1ToolsFacebookDownloadData = {
1649
+ query: {
1650
+ /**
1651
+ * Facebook video or reel URL
1652
+ */
1653
+ url: string;
1654
+ };
1655
+ };
1656
+
1657
+ export type GetV1ToolsFacebookDownloadResponse = ({
1658
+ success?: boolean;
1659
+ title?: string;
1660
+ downloadUrl?: string;
1661
+ thumbnail?: string;
1662
+ });
1663
+
1664
+ export type GetV1ToolsFacebookDownloadError = unknown;
1665
+
1666
+ export type GetV1ToolsLinkedinDownloadData = {
1667
+ query: {
1668
+ /**
1669
+ * LinkedIn post URL
1670
+ */
1671
+ url: string;
1672
+ };
1673
+ };
1674
+
1675
+ export type GetV1ToolsLinkedinDownloadResponse = ({
1676
+ success?: boolean;
1677
+ title?: string;
1678
+ downloadUrl?: string;
1679
+ });
1680
+
1681
+ export type GetV1ToolsLinkedinDownloadError = unknown;
1682
+
1683
+ export type GetV1ToolsBlueskyDownloadData = {
1684
+ query: {
1685
+ /**
1686
+ * Bluesky post URL
1687
+ */
1688
+ url: string;
1689
+ };
1690
+ };
1691
+
1692
+ export type GetV1ToolsBlueskyDownloadResponse = ({
1693
+ success?: boolean;
1694
+ title?: string;
1695
+ text?: string;
1696
+ downloadUrl?: string;
1697
+ thumbnail?: string;
1698
+ });
1699
+
1700
+ export type GetV1ToolsBlueskyDownloadError = unknown;
1701
+
1702
+ export type GetV1AnalyticsData = {
1703
+ query?: {
1704
+ /**
1705
+ * Inclusive lower bound
1706
+ */
1707
+ fromDate?: string;
1708
+ /**
1709
+ * Page size (default 50)
1710
+ */
1711
+ limit?: number;
1712
+ /**
1713
+ * Sort order
1714
+ */
1715
+ order?: 'asc' | 'desc';
1716
+ /**
1717
+ * Page number (default 1)
1718
+ */
1719
+ page?: number;
1720
+ /**
1721
+ * Filter by platform (default "all")
1722
+ */
1723
+ platform?: string;
1724
+ /**
1725
+ * Returns analytics for a single post. Accepts both Late Post IDs (from `POST /v1/posts`)
1726
+ * and External Post IDs (from this endpoint's list response). The API automatically
1727
+ * resolves Late Post IDs to their corresponding External Post analytics.
1728
+ *
1729
+ */
1730
+ postId?: string;
1731
+ /**
1732
+ * Filter by profile ID (default "all")
1733
+ */
1734
+ profileId?: string;
1735
+ /**
1736
+ * Sort by date or engagement
1737
+ */
1738
+ sortBy?: 'date' | 'engagement';
1739
+ /**
1740
+ * Inclusive upper bound
1741
+ */
1742
+ toDate?: string;
1743
+ };
1744
+ };
1745
+
1746
+ export type GetV1AnalyticsResponse = ((AnalyticsSinglePostResponse | AnalyticsListResponse));
1747
+
1748
+ export type GetV1AnalyticsError = ({
1749
+ error?: string;
1750
+ } | {
1751
+ error?: string;
1752
+ code?: string;
1753
+ } | ErrorResponse);
1754
+
1755
+ export type GetV1AnalyticsYoutubeDailyViewsData = {
1756
+ query: {
1757
+ /**
1758
+ * The Late account ID for the YouTube account
1759
+ */
1760
+ accountId: string;
1761
+ /**
1762
+ * End date (YYYY-MM-DD). Defaults to 3 days ago (YouTube data latency).
1763
+ */
1764
+ endDate?: string;
1765
+ /**
1766
+ * Start date (YYYY-MM-DD). Defaults to 30 days ago.
1767
+ */
1768
+ startDate?: string;
1769
+ /**
1770
+ * The YouTube video ID (e.g., "dQw4w9WgXcQ")
1771
+ */
1772
+ videoId: string;
1773
+ };
1774
+ };
1775
+
1776
+ export type GetV1AnalyticsYoutubeDailyViewsResponse = (YouTubeDailyViewsResponse);
1777
+
1778
+ export type GetV1AnalyticsYoutubeDailyViewsError = ({
1779
+ error?: string;
1780
+ } | {
1781
+ error?: string;
1782
+ code?: string;
1783
+ } | YouTubeScopeMissingResponse | {
1784
+ success?: boolean;
1785
+ error?: string;
1786
+ });
1787
+
1788
+ export type GetV1AccountGroupsResponse = ({
1789
+ groups?: Array<{
1790
+ _id?: string;
1791
+ name?: string;
1792
+ accountIds?: Array<(string)>;
1793
+ }>;
1794
+ });
1795
+
1796
+ export type GetV1AccountGroupsError = ({
1797
+ error?: string;
1798
+ });
1799
+
1800
+ export type PostV1AccountGroupsData = {
1801
+ body: {
1802
+ name: string;
1803
+ accountIds: Array<(string)>;
1804
+ };
1805
+ };
1806
+
1807
+ export type PostV1AccountGroupsResponse = ({
1808
+ message?: string;
1809
+ group?: {
1810
+ _id?: string;
1811
+ name?: string;
1812
+ accountIds?: Array<(string)>;
1813
+ };
1814
+ });
1815
+
1816
+ export type PostV1AccountGroupsError = (unknown | {
1817
+ error?: string;
1818
+ });
1819
+
1820
+ export type PutV1AccountGroupsByGroupIdData = {
1821
+ body: {
1822
+ name?: string;
1823
+ accountIds?: Array<(string)>;
1824
+ };
1825
+ path: {
1826
+ groupId: string;
1827
+ };
1828
+ };
1829
+
1830
+ export type PutV1AccountGroupsByGroupIdResponse = ({
1831
+ message?: string;
1832
+ group?: {
1833
+ [key: string]: unknown;
1834
+ };
1835
+ });
1836
+
1837
+ export type PutV1AccountGroupsByGroupIdError = ({
1838
+ error?: string;
1839
+ } | unknown);
1840
+
1841
+ export type DeleteV1AccountGroupsByGroupIdData = {
1842
+ path: {
1843
+ groupId: string;
1844
+ };
1845
+ };
1846
+
1847
+ export type DeleteV1AccountGroupsByGroupIdResponse = ({
1848
+ message?: string;
1849
+ });
1850
+
1851
+ export type DeleteV1AccountGroupsByGroupIdError = ({
1852
+ error?: string;
1853
+ });
1854
+
1855
+ export type PostV1MediaPresignData = {
1856
+ body: {
1857
+ /**
1858
+ * Name of the file to upload
1859
+ */
1860
+ filename: string;
1861
+ /**
1862
+ * MIME type of the file
1863
+ */
1864
+ contentType: 'image/jpeg' | 'image/jpg' | 'image/png' | 'image/webp' | 'image/gif' | 'video/mp4' | 'video/mpeg' | 'video/quicktime' | 'video/avi' | 'video/x-msvideo' | 'video/webm' | 'video/x-m4v' | 'application/pdf';
1865
+ /**
1866
+ * Optional file size in bytes for pre-validation (max 5GB)
1867
+ */
1868
+ size?: number;
1869
+ };
1870
+ };
1871
+
1872
+ export type PostV1MediaPresignResponse = ({
1873
+ /**
1874
+ * Presigned URL to PUT your file to (expires in 1 hour)
1875
+ */
1876
+ uploadUrl?: string;
1877
+ /**
1878
+ * Public URL where the file will be accessible after upload
1879
+ */
1880
+ publicUrl?: string;
1881
+ /**
1882
+ * Storage key/path of the file
1883
+ */
1884
+ key?: string;
1885
+ /**
1886
+ * Detected file type based on content type
1887
+ */
1888
+ type?: 'image' | 'video' | 'document';
1889
+ });
1890
+
1891
+ export type PostV1MediaPresignError = ({
1892
+ error?: string;
1893
+ });
1894
+
1895
+ export type GetV1RedditSearchData = {
1896
+ query: {
1897
+ accountId: string;
1898
+ after?: string;
1899
+ limit?: number;
1900
+ q: string;
1901
+ restrict_sr?: '0' | '1';
1902
+ sort?: 'relevance' | 'hot' | 'top' | 'new' | 'comments';
1903
+ subreddit?: string;
1904
+ };
1905
+ };
1906
+
1907
+ export type GetV1RedditSearchResponse = ({
1908
+ posts?: Array<{
1909
+ id?: string;
1910
+ title?: string;
1911
+ selftext?: string;
1912
+ author?: string;
1913
+ subreddit?: string;
1914
+ score?: number;
1915
+ num_comments?: number;
1916
+ created_utc?: number;
1917
+ permalink?: string;
1918
+ }>;
1919
+ after?: string;
1920
+ });
1921
+
1922
+ export type GetV1RedditSearchError = (unknown | {
1923
+ error?: string;
1924
+ });
1925
+
1926
+ export type GetV1RedditFeedData = {
1927
+ query: {
1928
+ accountId: string;
1929
+ after?: string;
1930
+ limit?: number;
1931
+ sort?: 'hot' | 'new' | 'top' | 'rising';
1932
+ subreddit?: string;
1933
+ t?: 'hour' | 'day' | 'week' | 'month' | 'year' | 'all';
1934
+ };
1935
+ };
1936
+
1937
+ export type GetV1RedditFeedResponse = ({
1938
+ posts?: Array<{
1939
+ [key: string]: unknown;
1940
+ }>;
1941
+ after?: string;
1942
+ });
1943
+
1944
+ export type GetV1RedditFeedError = (unknown | {
1945
+ error?: string;
1946
+ });
1947
+
1948
+ export type GetV1UsageStatsResponse = (UsageStats);
1949
+
1950
+ export type GetV1UsageStatsError = ({
1951
+ error?: string;
1952
+ });
1953
+
1954
+ export type GetV1PostsData = {
1955
+ query?: {
1956
+ createdBy?: string;
1957
+ dateFrom?: string;
1958
+ dateTo?: string;
1959
+ includeHidden?: boolean;
1960
+ /**
1961
+ * Page size
1962
+ */
1963
+ limit?: number;
1964
+ /**
1965
+ * Page number (1-based)
1966
+ */
1967
+ page?: number;
1968
+ platform?: string;
1969
+ profileId?: string;
1970
+ status?: 'draft' | 'scheduled' | 'published' | 'failed';
1971
+ };
1972
+ };
1973
+
1974
+ export type GetV1PostsResponse = (PostsListResponse);
1975
+
1976
+ export type GetV1PostsError = ({
1977
+ error?: string;
1978
+ });
1979
+
1980
+ export type PostV1PostsData = {
1981
+ body: {
1982
+ title?: string;
1983
+ content?: string;
1984
+ mediaItems?: Array<{
1985
+ type?: 'image' | 'video' | 'gif' | 'document';
1986
+ url?: string;
1987
+ }>;
1988
+ platforms?: Array<{
1989
+ platform?: string;
1990
+ accountId?: string;
1991
+ customContent?: string;
1992
+ customMedia?: Array<{
1993
+ type?: 'image' | 'video' | 'gif' | 'document';
1994
+ url?: string;
1995
+ }>;
1996
+ /**
1997
+ * Optional per-platform scheduled time override. When omitted, the top-level scheduledFor is used.
1998
+ */
1999
+ scheduledFor?: string;
2000
+ platformSpecificData?: (TwitterPlatformData | ThreadsPlatformData | FacebookPlatformData | InstagramPlatformData | LinkedInPlatformData | PinterestPlatformData | YouTubePlatformData | TikTokPlatformData | TelegramPlatformData | SnapchatPlatformData);
2001
+ }>;
2002
+ scheduledFor?: string;
2003
+ publishNow?: boolean;
2004
+ isDraft?: boolean;
2005
+ timezone?: string;
2006
+ /**
2007
+ * Tags/keywords for the post. YouTube-specific constraints:
2008
+ * - No count limit; duplicates are automatically removed
2009
+ * - Each tag must be ≤ 100 characters
2010
+ * - Combined total across all tags ≤ 500 characters (YouTube's limit)
2011
+ *
2012
+ */
2013
+ tags?: Array<(string)>;
2014
+ hashtags?: Array<(string)>;
2015
+ mentions?: Array<(string)>;
2016
+ crosspostingEnabled?: boolean;
2017
+ metadata?: {
2018
+ [key: string]: unknown;
2019
+ };
2020
+ /**
2021
+ * Profile ID to schedule via queue. When provided without scheduledFor,
2022
+ * the post will be automatically assigned to the next available slot
2023
+ * from the profile's default queue (or the queue specified by queueId).
2024
+ *
2025
+ */
2026
+ queuedFromProfile?: string;
2027
+ /**
2028
+ * Specific queue ID to use when scheduling via queue.
2029
+ * Only used when queuedFromProfile is also provided.
2030
+ * If omitted, uses the profile's default queue.
2031
+ *
2032
+ */
2033
+ queueId?: string;
2034
+ };
2035
+ };
2036
+
2037
+ export type PostV1PostsResponse = (PostCreateResponse);
2038
+
2039
+ export type PostV1PostsError = ({
2040
+ error?: string;
2041
+ });
2042
+
2043
+ export type GetV1PostsByPostIdData = {
2044
+ path: {
2045
+ postId: string;
2046
+ };
2047
+ };
2048
+
2049
+ export type GetV1PostsByPostIdResponse = (PostGetResponse);
2050
+
2051
+ export type GetV1PostsByPostIdError = ({
2052
+ error?: string;
2053
+ } | unknown);
2054
+
2055
+ export type PutV1PostsByPostIdData = {
2056
+ body: {
2057
+ [key: string]: unknown;
2058
+ };
2059
+ path: {
2060
+ postId: string;
2061
+ };
2062
+ };
2063
+
2064
+ export type PutV1PostsByPostIdResponse = (PostUpdateResponse | unknown);
2065
+
2066
+ export type PutV1PostsByPostIdError = (unknown | {
2067
+ error?: string;
2068
+ });
2069
+
2070
+ export type DeleteV1PostsByPostIdData = {
2071
+ path: {
2072
+ postId: string;
2073
+ };
2074
+ };
2075
+
2076
+ export type DeleteV1PostsByPostIdResponse = (PostDeleteResponse);
2077
+
2078
+ export type DeleteV1PostsByPostIdError = (unknown | {
2079
+ error?: string;
2080
+ });
2081
+
2082
+ export type PostV1PostsBulkUploadData = {
2083
+ body: {
2084
+ file?: (Blob | File);
2085
+ };
2086
+ query?: {
2087
+ dryRun?: boolean;
2088
+ };
2089
+ };
2090
+
2091
+ export type PostV1PostsBulkUploadResponse = ({
2092
+ success?: boolean;
2093
+ totalRows?: number;
2094
+ created?: number;
2095
+ failed?: number;
2096
+ errors?: Array<{
2097
+ row?: number;
2098
+ error?: string;
2099
+ }>;
2100
+ posts?: Array<Post>;
2101
+ } | unknown);
2102
+
2103
+ export type PostV1PostsBulkUploadError = (unknown | {
2104
+ error?: string;
2105
+ });
2106
+
2107
+ export type PostV1PostsByPostIdRetryData = {
2108
+ path: {
2109
+ postId: string;
2110
+ };
2111
+ };
2112
+
2113
+ export type PostV1PostsByPostIdRetryResponse = (PostRetryResponse | unknown);
2114
+
2115
+ export type PostV1PostsByPostIdRetryError = (unknown | {
2116
+ error?: string;
2117
+ });
2118
+
2119
+ export type GetV1UsersResponse = ({
2120
+ currentUserId?: string;
2121
+ users?: Array<{
2122
+ _id?: string;
2123
+ name?: string;
2124
+ email?: string;
2125
+ role?: string;
2126
+ isRoot?: boolean;
2127
+ profileAccess?: Array<(string)>;
2128
+ createdAt?: string;
2129
+ }>;
2130
+ });
2131
+
2132
+ export type GetV1UsersError = ({
2133
+ error?: string;
2134
+ });
2135
+
2136
+ export type GetV1UsersByUserIdData = {
2137
+ path: {
2138
+ userId: string;
2139
+ };
2140
+ };
2141
+
2142
+ export type GetV1UsersByUserIdResponse = ({
2143
+ user?: {
2144
+ _id?: string;
2145
+ name?: string;
2146
+ email?: string;
2147
+ role?: string;
2148
+ isRoot?: boolean;
2149
+ profileAccess?: Array<(string)>;
2150
+ };
2151
+ });
2152
+
2153
+ export type GetV1UsersByUserIdError = ({
2154
+ error?: string;
2155
+ } | unknown);
2156
+
2157
+ export type GetV1ProfilesData = {
2158
+ query?: {
2159
+ /**
2160
+ * When true, includes profiles that exceed the user's plan limit.
2161
+ * Over-limit profiles will have `isOverLimit: true` in the response.
2162
+ * Useful for managing/deleting profiles after a plan downgrade.
2163
+ *
2164
+ */
2165
+ includeOverLimit?: boolean;
2166
+ };
2167
+ };
2168
+
2169
+ export type GetV1ProfilesResponse = (ProfilesListResponse);
2170
+
2171
+ export type GetV1ProfilesError = ({
2172
+ error?: string;
2173
+ });
2174
+
2175
+ export type PostV1ProfilesData = {
2176
+ body: {
2177
+ name: string;
2178
+ description?: string;
2179
+ color?: string;
2180
+ };
2181
+ };
2182
+
2183
+ export type PostV1ProfilesResponse = (ProfileCreateResponse);
2184
+
2185
+ export type PostV1ProfilesError = (unknown | {
2186
+ error?: string;
2187
+ });
2188
+
2189
+ export type GetV1ProfilesByProfileIdData = {
2190
+ path: {
2191
+ profileId: string;
2192
+ };
2193
+ };
2194
+
2195
+ export type GetV1ProfilesByProfileIdResponse = ({
2196
+ profile?: Profile;
2197
+ });
2198
+
2199
+ export type GetV1ProfilesByProfileIdError = ({
2200
+ error?: string;
2201
+ });
2202
+
2203
+ export type PutV1ProfilesByProfileIdData = {
2204
+ body: {
2205
+ name?: string;
2206
+ description?: string;
2207
+ color?: string;
2208
+ isDefault?: boolean;
2209
+ };
2210
+ path: {
2211
+ profileId: string;
2212
+ };
2213
+ };
2214
+
2215
+ export type PutV1ProfilesByProfileIdResponse = ({
2216
+ message?: string;
2217
+ profile?: Profile;
2218
+ });
2219
+
2220
+ export type PutV1ProfilesByProfileIdError = ({
2221
+ error?: string;
2222
+ });
2223
+
2224
+ export type DeleteV1ProfilesByProfileIdData = {
2225
+ path: {
2226
+ profileId: string;
2227
+ };
2228
+ };
2229
+
2230
+ export type DeleteV1ProfilesByProfileIdResponse = ({
2231
+ message?: string;
2232
+ });
2233
+
2234
+ export type DeleteV1ProfilesByProfileIdError = (unknown | {
2235
+ error?: string;
2236
+ });
2237
+
2238
+ export type GetV1AccountsData = {
2239
+ query?: {
2240
+ /**
2241
+ * When true, includes accounts from profiles that exceed the user's plan limit.
2242
+ * Useful for disconnecting accounts from over-limit profiles so they can be deleted.
2243
+ *
2244
+ */
2245
+ includeOverLimit?: boolean;
2246
+ /**
2247
+ * Filter accounts by profile ID
2248
+ */
2249
+ profileId?: string;
2250
+ };
2251
+ };
2252
+
2253
+ export type GetV1AccountsResponse = ({
2254
+ accounts?: Array<SocialAccount>;
2255
+ /**
2256
+ * Whether user has analytics add-on access
2257
+ */
2258
+ hasAnalyticsAccess?: boolean;
2259
+ });
2260
+
2261
+ export type GetV1AccountsError = ({
2262
+ error?: string;
2263
+ });
2264
+
2265
+ export type GetV1AccountsFollowerStatsData = {
2266
+ query?: {
2267
+ /**
2268
+ * Comma-separated list of account IDs (optional, defaults to all user's accounts)
2269
+ */
2270
+ accountIds?: string;
2271
+ /**
2272
+ * Start date in YYYY-MM-DD format (defaults to 30 days ago)
2273
+ */
2274
+ fromDate?: string;
2275
+ /**
2276
+ * Data aggregation level
2277
+ */
2278
+ granularity?: 'daily' | 'weekly' | 'monthly';
2279
+ /**
2280
+ * Filter by profile ID
2281
+ */
2282
+ profileId?: string;
2283
+ /**
2284
+ * End date in YYYY-MM-DD format (defaults to today)
2285
+ */
2286
+ toDate?: string;
2287
+ };
2288
+ };
2289
+
2290
+ export type GetV1AccountsFollowerStatsResponse = ({
2291
+ accounts?: Array<AccountWithFollowerStats>;
2292
+ stats?: {
2293
+ [key: string]: Array<{
2294
+ date?: string;
2295
+ followers?: number;
2296
+ }>;
2297
+ };
2298
+ dateRange?: {
2299
+ from?: string;
2300
+ to?: string;
2301
+ };
2302
+ granularity?: string;
2303
+ });
2304
+
2305
+ export type GetV1AccountsFollowerStatsError = ({
2306
+ error?: string;
2307
+ } | {
2308
+ error?: string;
2309
+ message?: string;
2310
+ requiresAddon?: boolean;
2311
+ });
2312
+
2313
+ export type PutV1AccountsByAccountIdData = {
2314
+ body: {
2315
+ username?: string;
2316
+ displayName?: string;
2317
+ };
2318
+ path: {
2319
+ accountId: string;
2320
+ };
2321
+ };
2322
+
2323
+ export type PutV1AccountsByAccountIdResponse = ({
2324
+ message?: string;
2325
+ username?: string;
2326
+ displayName?: string;
2327
+ });
2328
+
2329
+ export type PutV1AccountsByAccountIdError = (unknown | {
2330
+ error?: string;
2331
+ });
2332
+
2333
+ export type DeleteV1AccountsByAccountIdData = {
2334
+ path: {
2335
+ accountId: string;
2336
+ };
2337
+ };
2338
+
2339
+ export type DeleteV1AccountsByAccountIdResponse = ({
2340
+ message?: string;
2341
+ });
2342
+
2343
+ export type DeleteV1AccountsByAccountIdError = ({
2344
+ error?: string;
2345
+ });
2346
+
2347
+ export type GetV1AccountsHealthData = {
2348
+ query?: {
2349
+ /**
2350
+ * Filter by platform
2351
+ */
2352
+ platform?: 'facebook' | 'instagram' | 'linkedin' | 'twitter' | 'tiktok' | 'youtube' | 'threads' | 'pinterest' | 'reddit' | 'bluesky' | 'googlebusiness' | 'telegram' | 'snapchat';
2353
+ /**
2354
+ * Filter by profile ID
2355
+ */
2356
+ profileId?: string;
2357
+ /**
2358
+ * Filter by health status
2359
+ */
2360
+ status?: 'healthy' | 'warning' | 'error';
2361
+ };
2362
+ };
2363
+
2364
+ export type GetV1AccountsHealthResponse = ({
2365
+ summary?: {
2366
+ /**
2367
+ * Total number of accounts
2368
+ */
2369
+ total?: number;
2370
+ /**
2371
+ * Number of healthy accounts
2372
+ */
2373
+ healthy?: number;
2374
+ /**
2375
+ * Number of accounts with warnings
2376
+ */
2377
+ warning?: number;
2378
+ /**
2379
+ * Number of accounts with errors
2380
+ */
2381
+ error?: number;
2382
+ /**
2383
+ * Number of accounts needing reconnection
2384
+ */
2385
+ needsReconnect?: number;
2386
+ };
2387
+ accounts?: Array<{
2388
+ accountId?: string;
2389
+ platform?: string;
2390
+ username?: string;
2391
+ displayName?: string;
2392
+ profileId?: string;
2393
+ status?: 'healthy' | 'warning' | 'error';
2394
+ canPost?: boolean;
2395
+ canFetchAnalytics?: boolean;
2396
+ tokenValid?: boolean;
2397
+ tokenExpiresAt?: string;
2398
+ needsReconnect?: boolean;
2399
+ issues?: Array<(string)>;
2400
+ }>;
2401
+ });
2402
+
2403
+ export type GetV1AccountsHealthError = ({
2404
+ error?: string;
2405
+ });
2406
+
2407
+ export type GetV1AccountsByAccountIdHealthData = {
2408
+ path: {
2409
+ /**
2410
+ * The account ID to check
2411
+ */
2412
+ accountId: string;
2413
+ };
2414
+ };
2415
+
2416
+ export type GetV1AccountsByAccountIdHealthResponse = ({
2417
+ accountId?: string;
2418
+ platform?: string;
2419
+ username?: string;
2420
+ displayName?: string;
2421
+ /**
2422
+ * Overall health status
2423
+ */
2424
+ status?: 'healthy' | 'warning' | 'error';
2425
+ tokenStatus?: {
2426
+ /**
2427
+ * Whether the token is valid
2428
+ */
2429
+ valid?: boolean;
2430
+ expiresAt?: string;
2431
+ /**
2432
+ * Human-readable time until expiry
2433
+ */
2434
+ expiresIn?: string;
2435
+ /**
2436
+ * Whether token expires within 24 hours
2437
+ */
2438
+ needsRefresh?: boolean;
2439
+ };
2440
+ permissions?: {
2441
+ posting?: Array<{
2442
+ scope?: string;
2443
+ granted?: boolean;
2444
+ required?: boolean;
2445
+ }>;
2446
+ analytics?: Array<{
2447
+ scope?: string;
2448
+ granted?: boolean;
2449
+ required?: boolean;
2450
+ }>;
2451
+ optional?: Array<{
2452
+ scope?: string;
2453
+ granted?: boolean;
2454
+ required?: boolean;
2455
+ }>;
2456
+ canPost?: boolean;
2457
+ canFetchAnalytics?: boolean;
2458
+ missingRequired?: Array<(string)>;
2459
+ };
2460
+ /**
2461
+ * List of issues found
2462
+ */
2463
+ issues?: Array<(string)>;
2464
+ /**
2465
+ * Actionable recommendations to fix issues
2466
+ */
2467
+ recommendations?: Array<(string)>;
2468
+ });
2469
+
2470
+ export type GetV1AccountsByAccountIdHealthError = ({
2471
+ error?: string;
2472
+ });
2473
+
2474
+ export type GetV1ApiKeysResponse = ({
2475
+ apiKeys?: Array<ApiKey>;
2476
+ });
2477
+
2478
+ export type GetV1ApiKeysError = ({
2479
+ error?: string;
2480
+ });
2481
+
2482
+ export type PostV1ApiKeysData = {
2483
+ body: {
2484
+ name: string;
2485
+ /**
2486
+ * Days until expiry
2487
+ */
2488
+ expiresIn?: number;
2489
+ };
2490
+ };
2491
+
2492
+ export type PostV1ApiKeysResponse = ({
2493
+ message?: string;
2494
+ apiKey?: ApiKey;
2495
+ });
2496
+
2497
+ export type PostV1ApiKeysError = (unknown | {
2498
+ error?: string;
2499
+ });
2500
+
2501
+ export type DeleteV1ApiKeysByKeyIdData = {
2502
+ path: {
2503
+ keyId: string;
2504
+ };
2505
+ };
2506
+
2507
+ export type DeleteV1ApiKeysByKeyIdResponse = ({
2508
+ message?: string;
2509
+ });
2510
+
2511
+ export type DeleteV1ApiKeysByKeyIdError = ({
2512
+ error?: string;
2513
+ });
2514
+
2515
+ export type PostV1InviteTokensData = {
2516
+ body: {
2517
+ /**
2518
+ * 'all' grants access to all profiles, 'profiles' restricts to specific profiles
2519
+ */
2520
+ scope: 'all' | 'profiles';
2521
+ /**
2522
+ * Required if scope is 'profiles'. Array of profile IDs to grant access to.
2523
+ */
2524
+ profileIds?: Array<(string)>;
2525
+ };
2526
+ };
2527
+
2528
+ export type PostV1InviteTokensResponse = ({
2529
+ token?: string;
2530
+ scope?: string;
2531
+ invitedProfileIds?: Array<(string)>;
2532
+ expiresAt?: string;
2533
+ inviteUrl?: string;
2534
+ });
2535
+
2536
+ export type PostV1InviteTokensError = (unknown | {
2537
+ error?: string;
2538
+ });
2539
+
2540
+ export type GetV1PlatformInvitesData = {
2541
+ query?: {
2542
+ /**
2543
+ * Optional. Filter invites by profile ID
2544
+ */
2545
+ profileId?: string;
2546
+ };
2547
+ };
2548
+
2549
+ export type GetV1PlatformInvitesResponse = ({
2550
+ invites?: Array<{
2551
+ _id?: string;
2552
+ token?: string;
2553
+ userId?: string;
2554
+ /**
2555
+ * Populated profile object (not a string ID)
2556
+ */
2557
+ profileId?: {
2558
+ _id?: string;
2559
+ name?: string;
2560
+ };
2561
+ platform?: string;
2562
+ inviterName?: string;
2563
+ inviterEmail?: string;
2564
+ expiresAt?: string;
2565
+ isUsed?: boolean;
2566
+ createdAt?: string;
2567
+ }>;
2568
+ });
2569
+
2570
+ export type GetV1PlatformInvitesError = ({
2571
+ error?: string;
2572
+ });
2573
+
2574
+ export type PostV1PlatformInvitesData = {
2575
+ body: {
2576
+ /**
2577
+ * Profile ID to connect the account to
2578
+ */
2579
+ profileId: string;
2580
+ /**
2581
+ * Platform to connect
2582
+ */
2583
+ platform: 'facebook' | 'instagram' | 'linkedin' | 'twitter' | 'threads' | 'tiktok' | 'youtube' | 'pinterest' | 'reddit' | 'bluesky' | 'googlebusiness' | 'telegram' | 'snapchat';
2584
+ };
2585
+ };
2586
+
2587
+ export type PostV1PlatformInvitesResponse = ({
2588
+ invite?: {
2589
+ _id?: string;
2590
+ token?: string;
2591
+ userId?: string;
2592
+ /**
2593
+ * Populated profile object (not a string ID)
2594
+ */
2595
+ profileId?: {
2596
+ _id?: string;
2597
+ name?: string;
2598
+ };
2599
+ platform?: string;
2600
+ inviterName?: string;
2601
+ inviterEmail?: string;
2602
+ expiresAt?: string;
2603
+ isUsed?: boolean;
2604
+ createdAt?: string;
2605
+ inviteUrl?: string;
2606
+ };
2607
+ });
2608
+
2609
+ export type PostV1PlatformInvitesError = (unknown | {
2610
+ error?: string;
2611
+ });
2612
+
2613
+ export type DeleteV1PlatformInvitesData = {
2614
+ query: {
2615
+ /**
2616
+ * Invite ID to revoke
2617
+ */
2618
+ id: string;
2619
+ };
2620
+ };
2621
+
2622
+ export type DeleteV1PlatformInvitesResponse = ({
2623
+ message?: string;
2624
+ });
2625
+
2626
+ export type DeleteV1PlatformInvitesError = (unknown | {
2627
+ error?: string;
2628
+ });
2629
+
2630
+ export type GetV1ConnectByPlatformData = {
2631
+ path: {
2632
+ /**
2633
+ * Social media platform to connect
2634
+ */
2635
+ platform: 'facebook' | 'instagram' | 'linkedin' | 'twitter' | 'tiktok' | 'youtube' | 'threads' | 'reddit' | 'pinterest' | 'bluesky' | 'googlebusiness' | 'telegram' | 'snapchat';
2636
+ };
2637
+ query: {
2638
+ /**
2639
+ * Your Late profile ID (get from /v1/profiles)
2640
+ */
2641
+ profileId: string;
2642
+ /**
2643
+ * Optional: Your custom redirect URL after connection completes.
2644
+ *
2645
+ * **Standard Mode:** Omit `headless=true` to use our hosted page selection UI.
2646
+ * After the user selects a Facebook Page, Late redirects here with:
2647
+ * `?connected=facebook&profileId=X&username=Y`
2648
+ *
2649
+ * **Headless Mode (Facebook, LinkedIn, Pinterest, Google Business Profile & Snapchat):**
2650
+ * Pass `headless=true` as a query parameter on this endpoint (not inside `redirect_url`), e.g.:
2651
+ * `GET /v1/connect/facebook?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
2652
+ * `GET /v1/connect/linkedin?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
2653
+ * `GET /v1/connect/pinterest?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
2654
+ * `GET /v1/connect/googlebusiness?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
2655
+ * `GET /v1/connect/snapchat?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
2656
+ *
2657
+ * After OAuth, the user is redirected directly to your `redirect_url` with OAuth data:
2658
+ * - **Facebook:** `?profileId=X&tempToken=Y&userProfile=Z&connect_token=CT&platform=facebook&step=select_page`
2659
+ * - **LinkedIn:** `?profileId=X&tempToken=Y&userProfile=Z&organizations=ORGS&connect_token=CT&platform=linkedin&step=select_organization`
2660
+ * (organizations contains `id`, `urn`, `name` only - use `/v1/connect/linkedin/organizations` to fetch full details)
2661
+ * - **Pinterest:** `?profileId=X&tempToken=Y&userProfile=Z&connect_token=CT&platform=pinterest&step=select_board`
2662
+ * - **Google Business:** `?profileId=X&tempToken=Y&userProfile=Z&connect_token=CT&platform=googlebusiness&step=select_location`
2663
+ * - **Snapchat:** `?profileId=X&tempToken=Y&userProfile=Z&publicProfiles=PROFILES&connect_token=CT&platform=snapchat&step=select_public_profile`
2664
+ * (publicProfiles contains `id`, `display_name`, `username`, `profile_image_url`, `subscriber_count`)
2665
+ *
2666
+ * Then use the respective endpoints to build your custom UI:
2667
+ * - Facebook: `/v1/connect/facebook/select-page` (GET to fetch, POST to save)
2668
+ * - LinkedIn: `/v1/connect/linkedin/organizations` (GET to fetch logos), `/v1/connect/linkedin/select-organization` (POST to save)
2669
+ * - Pinterest: `/v1/connect/pinterest/select-board` (GET to fetch, POST to save)
2670
+ * - Google Business: `/v1/connect/googlebusiness/locations` (GET) and `/v1/connect/googlebusiness/select-location` (POST)
2671
+ * - Snapchat: `/v1/connect/snapchat/select-profile` (POST to save selected public profile)
2672
+ *
2673
+ * Example: `https://yourdomain.com/integrations/callback`
2674
+ *
2675
+ */
2676
+ redirect_url?: string;
2677
+ };
2678
+ };
2679
+
2680
+ export type GetV1ConnectByPlatformResponse = ({
2681
+ /**
2682
+ * URL to redirect your user to for OAuth authorization
2683
+ */
2684
+ authUrl?: string;
2685
+ /**
2686
+ * State parameter for security (handled automatically)
2687
+ */
2688
+ state?: string;
2689
+ });
2690
+
2691
+ export type GetV1ConnectByPlatformError = (unknown | {
2692
+ error?: string;
2693
+ });
2694
+
2695
+ export type PostV1ConnectByPlatformData = {
2696
+ body: {
2697
+ code: string;
2698
+ state: string;
2699
+ profileId: string;
2700
+ };
2701
+ path: {
2702
+ platform: string;
2703
+ };
2704
+ };
2705
+
2706
+ export type PostV1ConnectByPlatformResponse = (unknown);
2707
+
2708
+ export type PostV1ConnectByPlatformError = (unknown | {
2709
+ error?: string;
2710
+ });
2711
+
2712
+ export type GetV1ConnectFacebookSelectPageData = {
2713
+ query: {
2714
+ /**
2715
+ * Profile ID from your connection flow
2716
+ */
2717
+ profileId: string;
2718
+ /**
2719
+ * Temporary Facebook access token from the OAuth callback redirect
2720
+ */
2721
+ tempToken: string;
2722
+ };
2723
+ };
2724
+
2725
+ export type GetV1ConnectFacebookSelectPageResponse = ({
2726
+ pages?: Array<{
2727
+ /**
2728
+ * Facebook Page ID
2729
+ */
2730
+ id?: string;
2731
+ /**
2732
+ * Page name
2733
+ */
2734
+ name?: string;
2735
+ /**
2736
+ * Page username/handle (may be null)
2737
+ */
2738
+ username?: string;
2739
+ /**
2740
+ * Page-specific access token
2741
+ */
2742
+ access_token?: string;
2743
+ /**
2744
+ * Page category
2745
+ */
2746
+ category?: string;
2747
+ /**
2748
+ * User permissions for this page
2749
+ */
2750
+ tasks?: Array<(string)>;
2751
+ }>;
2752
+ });
2753
+
2754
+ export type GetV1ConnectFacebookSelectPageError = (unknown | {
2755
+ error?: string;
2756
+ });
2757
+
2758
+ export type PostV1ConnectFacebookSelectPageData = {
2759
+ body: {
2760
+ /**
2761
+ * Profile ID from your connection flow
2762
+ */
2763
+ profileId: string;
2764
+ /**
2765
+ * The Facebook Page ID selected by the user
2766
+ */
2767
+ pageId: string;
2768
+ /**
2769
+ * Temporary Facebook access token from OAuth
2770
+ */
2771
+ tempToken: string;
2772
+ /**
2773
+ * Decoded user profile object from the OAuth callback
2774
+ */
2775
+ userProfile?: {
2776
+ id?: string;
2777
+ name?: string;
2778
+ profilePicture?: string;
2779
+ };
2780
+ /**
2781
+ * Optional custom redirect URL to return to after selection
2782
+ */
2783
+ redirect_url?: string;
2784
+ };
2785
+ };
2786
+
2787
+ export type PostV1ConnectFacebookSelectPageResponse = ({
2788
+ message?: string;
2789
+ /**
2790
+ * Redirect URL if custom redirect_url was provided
2791
+ */
2792
+ redirect_url?: string;
2793
+ account?: {
2794
+ platform?: 'facebook';
2795
+ username?: string;
2796
+ displayName?: string;
2797
+ profilePicture?: string;
2798
+ isActive?: boolean;
2799
+ selectedPageName?: string;
2800
+ };
2801
+ });
2802
+
2803
+ export type PostV1ConnectFacebookSelectPageError = (unknown | {
2804
+ error?: string;
2805
+ });
2806
+
2807
+ export type GetV1ConnectGooglebusinessLocationsData = {
2808
+ query: {
2809
+ /**
2810
+ * Profile ID from your connection flow
2811
+ */
2812
+ profileId: string;
2813
+ /**
2814
+ * Temporary Google access token from the OAuth callback redirect
2815
+ */
2816
+ tempToken: string;
2817
+ };
2818
+ };
2819
+
2820
+ export type GetV1ConnectGooglebusinessLocationsResponse = ({
2821
+ locations?: Array<{
2822
+ /**
2823
+ * Location ID
2824
+ */
2825
+ id?: string;
2826
+ /**
2827
+ * Business name
2828
+ */
2829
+ name?: string;
2830
+ /**
2831
+ * Google Business Account ID
2832
+ */
2833
+ accountId?: string;
2834
+ /**
2835
+ * Account name
2836
+ */
2837
+ accountName?: string;
2838
+ /**
2839
+ * Business address
2840
+ */
2841
+ address?: string;
2842
+ /**
2843
+ * Business category
2844
+ */
2845
+ category?: string;
2846
+ }>;
2847
+ });
2848
+
2849
+ export type GetV1ConnectGooglebusinessLocationsError = (unknown | {
2850
+ error?: string;
2851
+ });
2852
+
2853
+ export type PostV1ConnectGooglebusinessSelectLocationData = {
2854
+ body: {
2855
+ /**
2856
+ * Profile ID from your connection flow
2857
+ */
2858
+ profileId: string;
2859
+ /**
2860
+ * The Google Business location ID selected by the user
2861
+ */
2862
+ locationId: string;
2863
+ /**
2864
+ * Temporary Google access token from OAuth
2865
+ */
2866
+ tempToken: string;
2867
+ /**
2868
+ * Decoded user profile object from the OAuth callback. **Important:** This contains
2869
+ * the refresh token needed for token refresh. Always include this field.
2870
+ *
2871
+ */
2872
+ userProfile?: {
2873
+ id?: string;
2874
+ name?: string;
2875
+ /**
2876
+ * Google refresh token for long-lived access
2877
+ */
2878
+ refreshToken?: string;
2879
+ /**
2880
+ * Token expiration time in seconds
2881
+ */
2882
+ tokenExpiresIn?: number;
2883
+ /**
2884
+ * Granted OAuth scopes
2885
+ */
2886
+ scope?: string;
2887
+ };
2888
+ /**
2889
+ * Optional custom redirect URL to return to after selection
2890
+ */
2891
+ redirect_url?: string;
2892
+ };
2893
+ };
2894
+
2895
+ export type PostV1ConnectGooglebusinessSelectLocationResponse = ({
2896
+ message?: string;
2897
+ /**
2898
+ * Redirect URL if custom redirect_url was provided
2899
+ */
2900
+ redirect_url?: string;
2901
+ account?: {
2902
+ platform?: 'googlebusiness';
2903
+ username?: string;
2904
+ displayName?: string;
2905
+ isActive?: boolean;
2906
+ selectedLocationName?: string;
2907
+ selectedLocationId?: string;
2908
+ };
2909
+ });
2910
+
2911
+ export type PostV1ConnectGooglebusinessSelectLocationError = (unknown | {
2912
+ error?: string;
2913
+ });
2914
+
2915
+ export type GetV1AccountsByAccountIdGmbReviewsData = {
2916
+ path: {
2917
+ /**
2918
+ * The Late account ID (from /v1/accounts)
2919
+ */
2920
+ accountId: string;
2921
+ };
2922
+ query?: {
2923
+ /**
2924
+ * Number of reviews to fetch per page (max 50)
2925
+ */
2926
+ pageSize?: number;
2927
+ /**
2928
+ * Pagination token from previous response
2929
+ */
2930
+ pageToken?: string;
2931
+ };
2932
+ };
2933
+
2934
+ export type GetV1AccountsByAccountIdGmbReviewsResponse = ({
2935
+ success?: boolean;
2936
+ accountId?: string;
2937
+ locationId?: string;
2938
+ reviews?: Array<{
2939
+ /**
2940
+ * Review ID
2941
+ */
2942
+ id?: string;
2943
+ /**
2944
+ * Full resource name
2945
+ */
2946
+ name?: string;
2947
+ reviewer?: {
2948
+ displayName?: string;
2949
+ profilePhotoUrl?: (string) | null;
2950
+ isAnonymous?: boolean;
2951
+ };
2952
+ /**
2953
+ * Numeric star rating
2954
+ */
2955
+ rating?: number;
2956
+ /**
2957
+ * Google's string rating
2958
+ */
2959
+ starRating?: 'ONE' | 'TWO' | 'THREE' | 'FOUR' | 'FIVE';
2960
+ /**
2961
+ * Review text
2962
+ */
2963
+ comment?: string;
2964
+ createTime?: string;
2965
+ updateTime?: string;
2966
+ reviewReply?: {
2967
+ /**
2968
+ * Business owner reply
2969
+ */
2970
+ comment?: string;
2971
+ updateTime?: string;
2972
+ } | null;
2973
+ }>;
2974
+ /**
2975
+ * Overall average rating
2976
+ */
2977
+ averageRating?: number;
2978
+ /**
2979
+ * Total number of reviews
2980
+ */
2981
+ totalReviewCount?: number;
2982
+ /**
2983
+ * Token for next page
2984
+ */
2985
+ nextPageToken?: (string) | null;
2986
+ });
2987
+
2988
+ export type GetV1AccountsByAccountIdGmbReviewsError = (ErrorResponse | {
2989
+ error?: string;
2990
+ });
2991
+
2992
+ export type GetV1ConnectLinkedinOrganizationsData = {
2993
+ query: {
2994
+ /**
2995
+ * Comma-separated list of organization IDs to fetch details for (max 100)
2996
+ */
2997
+ orgIds: string;
2998
+ /**
2999
+ * The temporary LinkedIn access token from the OAuth redirect
3000
+ */
3001
+ tempToken: string;
3002
+ };
3003
+ };
3004
+
3005
+ export type GetV1ConnectLinkedinOrganizationsResponse = ({
3006
+ organizations?: Array<{
3007
+ /**
3008
+ * Organization ID
3009
+ */
3010
+ id?: string;
3011
+ /**
3012
+ * Logo URL (may be absent if no logo)
3013
+ */
3014
+ logoUrl?: string;
3015
+ /**
3016
+ * Organization's vanity name/slug
3017
+ */
3018
+ vanityName?: string;
3019
+ /**
3020
+ * Organization's website URL
3021
+ */
3022
+ website?: string;
3023
+ /**
3024
+ * Organization's primary industry
3025
+ */
3026
+ industry?: string;
3027
+ /**
3028
+ * Organization's description
3029
+ */
3030
+ description?: string;
3031
+ }>;
3032
+ });
3033
+
3034
+ export type GetV1ConnectLinkedinOrganizationsError = ({
3035
+ error?: string;
3036
+ } | unknown);
3037
+
3038
+ export type PostV1ConnectLinkedinSelectOrganizationData = {
3039
+ body: {
3040
+ profileId: string;
3041
+ tempToken: string;
3042
+ userProfile: {
3043
+ [key: string]: unknown;
3044
+ };
3045
+ accountType: 'personal' | 'organization';
3046
+ selectedOrganization?: {
3047
+ [key: string]: unknown;
3048
+ };
3049
+ redirect_url?: string;
3050
+ };
3051
+ };
3052
+
3053
+ export type PostV1ConnectLinkedinSelectOrganizationResponse = ({
3054
+ message?: string;
3055
+ account?: SocialAccount;
3056
+ });
3057
+
3058
+ export type PostV1ConnectLinkedinSelectOrganizationError = (unknown | {
3059
+ error?: string;
3060
+ });
3061
+
3062
+ export type GetV1ConnectPinterestSelectBoardData = {
3063
+ headers: {
3064
+ /**
3065
+ * Short-lived connect token from the OAuth redirect
3066
+ */
3067
+ 'X-Connect-Token': string;
3068
+ };
3069
+ query: {
3070
+ /**
3071
+ * Your Late profile ID
3072
+ */
3073
+ profileId: string;
3074
+ /**
3075
+ * Temporary Pinterest access token from the OAuth callback redirect
3076
+ */
3077
+ tempToken: string;
3078
+ };
3079
+ };
3080
+
3081
+ export type GetV1ConnectPinterestSelectBoardResponse = ({
3082
+ boards?: Array<{
3083
+ /**
3084
+ * Pinterest Board ID
3085
+ */
3086
+ id?: string;
3087
+ /**
3088
+ * Board name
3089
+ */
3090
+ name?: string;
3091
+ /**
3092
+ * Board description
3093
+ */
3094
+ description?: string;
3095
+ /**
3096
+ * Board privacy setting
3097
+ */
3098
+ privacy?: string;
3099
+ }>;
3100
+ });
3101
+
3102
+ export type GetV1ConnectPinterestSelectBoardError = (unknown | {
3103
+ error?: string;
3104
+ });
3105
+
3106
+ export type PostV1ConnectPinterestSelectBoardData = {
3107
+ body: {
3108
+ /**
3109
+ * Your Late profile ID
3110
+ */
3111
+ profileId: string;
3112
+ /**
3113
+ * The Pinterest Board ID selected by the user
3114
+ */
3115
+ boardId: string;
3116
+ /**
3117
+ * The board name (for display purposes)
3118
+ */
3119
+ boardName?: string;
3120
+ /**
3121
+ * Temporary Pinterest access token from OAuth
3122
+ */
3123
+ tempToken: string;
3124
+ /**
3125
+ * User profile data from OAuth redirect
3126
+ */
3127
+ userProfile?: {
3128
+ [key: string]: unknown;
3129
+ };
3130
+ /**
3131
+ * Pinterest refresh token (if available)
3132
+ */
3133
+ refreshToken?: string;
3134
+ /**
3135
+ * Token expiration time in seconds
3136
+ */
3137
+ expiresIn?: number;
3138
+ /**
3139
+ * Custom redirect URL after connection completes
3140
+ */
3141
+ redirect_url?: string;
3142
+ };
3143
+ };
3144
+
3145
+ export type PostV1ConnectPinterestSelectBoardResponse = ({
3146
+ message?: string;
3147
+ /**
3148
+ * Redirect URL with connection params (if provided)
3149
+ */
3150
+ redirect_url?: string;
3151
+ account?: {
3152
+ platform?: 'pinterest';
3153
+ username?: string;
3154
+ displayName?: string;
3155
+ profilePicture?: string;
3156
+ isActive?: boolean;
3157
+ defaultBoardName?: string;
3158
+ };
3159
+ });
3160
+
3161
+ export type PostV1ConnectPinterestSelectBoardError = (unknown | {
3162
+ error?: string;
3163
+ });
3164
+
3165
+ export type GetV1ConnectSnapchatSelectProfileData = {
3166
+ headers: {
3167
+ /**
3168
+ * Short-lived connect token from the OAuth redirect
3169
+ */
3170
+ 'X-Connect-Token': string;
3171
+ };
3172
+ query: {
3173
+ /**
3174
+ * Your Late profile ID
3175
+ */
3176
+ profileId: string;
3177
+ /**
3178
+ * Temporary Snapchat access token from the OAuth callback redirect
3179
+ */
3180
+ tempToken: string;
3181
+ };
3182
+ };
3183
+
3184
+ export type GetV1ConnectSnapchatSelectProfileResponse = ({
3185
+ publicProfiles?: Array<{
3186
+ /**
3187
+ * Snapchat Public Profile ID
3188
+ */
3189
+ id?: string;
3190
+ /**
3191
+ * Public profile display name
3192
+ */
3193
+ display_name?: string;
3194
+ /**
3195
+ * Public profile username/handle
3196
+ */
3197
+ username?: string;
3198
+ /**
3199
+ * Profile image URL
3200
+ */
3201
+ profile_image_url?: string;
3202
+ /**
3203
+ * Number of subscribers
3204
+ */
3205
+ subscriber_count?: number;
3206
+ }>;
3207
+ });
3208
+
3209
+ export type GetV1ConnectSnapchatSelectProfileError = (unknown | {
3210
+ error?: string;
3211
+ });
3212
+
3213
+ export type PostV1ConnectSnapchatSelectProfileData = {
3214
+ body: {
3215
+ /**
3216
+ * Your Late profile ID
3217
+ */
3218
+ profileId: string;
3219
+ /**
3220
+ * The selected Snapchat Public Profile
3221
+ */
3222
+ selectedPublicProfile: {
3223
+ /**
3224
+ * Snapchat Public Profile ID
3225
+ */
3226
+ id: string;
3227
+ /**
3228
+ * Display name of the public profile
3229
+ */
3230
+ display_name: string;
3231
+ /**
3232
+ * Username/handle
3233
+ */
3234
+ username?: string;
3235
+ /**
3236
+ * Profile image URL
3237
+ */
3238
+ profile_image_url?: string;
3239
+ /**
3240
+ * Number of subscribers
3241
+ */
3242
+ subscriber_count?: number;
3243
+ };
3244
+ /**
3245
+ * Temporary Snapchat access token from OAuth
3246
+ */
3247
+ tempToken: string;
3248
+ /**
3249
+ * User profile data from OAuth redirect
3250
+ */
3251
+ userProfile: {
3252
+ [key: string]: unknown;
3253
+ };
3254
+ /**
3255
+ * Snapchat refresh token (if available)
3256
+ */
3257
+ refreshToken?: string;
3258
+ /**
3259
+ * Token expiration time in seconds
3260
+ */
3261
+ expiresIn?: number;
3262
+ /**
3263
+ * Custom redirect URL after connection completes
3264
+ */
3265
+ redirect_url?: string;
3266
+ };
3267
+ headers?: {
3268
+ /**
3269
+ * Short-lived connect token from the OAuth redirect (for API users)
3270
+ */
3271
+ 'X-Connect-Token'?: string;
3272
+ };
3273
+ };
3274
+
3275
+ export type PostV1ConnectSnapchatSelectProfileResponse = ({
3276
+ message?: string;
3277
+ /**
3278
+ * Redirect URL with connection params (if provided in request)
3279
+ */
3280
+ redirect_url?: string;
3281
+ account?: {
3282
+ platform?: 'snapchat';
3283
+ username?: string;
3284
+ displayName?: string;
3285
+ profilePicture?: string;
3286
+ isActive?: boolean;
3287
+ publicProfileName?: string;
3288
+ };
3289
+ });
3290
+
3291
+ export type PostV1ConnectSnapchatSelectProfileError = (unknown | {
3292
+ error?: string;
3293
+ });
3294
+
3295
+ export type PostV1ConnectBlueskyCredentialsData = {
3296
+ body: {
3297
+ /**
3298
+ * Your Bluesky handle (e.g. user.bsky.social) or email address
3299
+ */
3300
+ identifier: string;
3301
+ /**
3302
+ * App password generated from Bluesky Settings > App Passwords
3303
+ */
3304
+ appPassword: string;
3305
+ /**
3306
+ * Required state parameter formatted as `{userId}-{profileId}`.
3307
+ * - `userId`: Your Late user ID (get from `GET /v1/users` → `currentUserId`)
3308
+ * - `profileId`: The profile ID to connect the account to (get from `GET /v1/profiles`)
3309
+ *
3310
+ */
3311
+ state: string;
3312
+ /**
3313
+ * Optional URL to redirect to after successful connection
3314
+ */
3315
+ redirectUri?: string;
3316
+ };
3317
+ };
3318
+
3319
+ export type PostV1ConnectBlueskyCredentialsResponse = ({
3320
+ message?: string;
3321
+ account?: SocialAccount;
3322
+ });
3323
+
3324
+ export type PostV1ConnectBlueskyCredentialsError = (unknown | {
3325
+ error?: string;
3326
+ });
3327
+
3328
+ export type GetV1ConnectTelegramData = {
3329
+ query: {
3330
+ /**
3331
+ * The profile ID to connect the Telegram account to
3332
+ */
3333
+ profileId: string;
3334
+ };
3335
+ };
3336
+
3337
+ export type GetV1ConnectTelegramResponse = ({
3338
+ /**
3339
+ * The access code to send to the Telegram bot
3340
+ */
3341
+ code?: string;
3342
+ /**
3343
+ * When the code expires
3344
+ */
3345
+ expiresAt?: string;
3346
+ /**
3347
+ * Seconds until expiration
3348
+ */
3349
+ expiresIn?: number;
3350
+ /**
3351
+ * The Telegram bot username to message
3352
+ */
3353
+ botUsername?: string;
3354
+ /**
3355
+ * Step-by-step connection instructions
3356
+ */
3357
+ instructions?: Array<(string)>;
3358
+ });
3359
+
3360
+ export type GetV1ConnectTelegramError = (unknown | {
3361
+ error?: string;
3362
+ });
3363
+
3364
+ export type PostV1ConnectTelegramData = {
3365
+ body: {
3366
+ /**
3367
+ * The Telegram chat ID. Can be:
3368
+ * - Numeric ID (e.g., "-1001234567890")
3369
+ * - Username with @ prefix (e.g., "@mychannel")
3370
+ *
3371
+ */
3372
+ chatId: string;
3373
+ /**
3374
+ * The profile ID to connect the account to
3375
+ */
3376
+ profileId: string;
3377
+ };
3378
+ };
3379
+
3380
+ export type PostV1ConnectTelegramResponse = ({
3381
+ message?: string;
3382
+ account?: {
3383
+ _id?: string;
3384
+ platform?: 'telegram';
3385
+ username?: string;
3386
+ displayName?: string;
3387
+ isActive?: boolean;
3388
+ chatType?: 'channel' | 'group' | 'supergroup' | 'private';
3389
+ };
3390
+ });
3391
+
3392
+ export type PostV1ConnectTelegramError = (unknown | {
3393
+ error?: string;
3394
+ });
3395
+
3396
+ export type PatchV1ConnectTelegramData = {
3397
+ query: {
3398
+ /**
3399
+ * The access code to check status for
3400
+ */
3401
+ code: string;
3402
+ };
3403
+ };
3404
+
3405
+ export type PatchV1ConnectTelegramResponse = (({
3406
+ status?: 'pending';
3407
+ expiresAt?: string;
3408
+ /**
3409
+ * Seconds until expiration
3410
+ */
3411
+ expiresIn?: number;
3412
+ } | {
3413
+ status?: 'connected';
3414
+ chatId?: string;
3415
+ chatTitle?: string;
3416
+ chatType?: 'channel' | 'group' | 'supergroup';
3417
+ account?: {
3418
+ _id?: string;
3419
+ platform?: string;
3420
+ username?: string;
3421
+ displayName?: string;
3422
+ };
3423
+ } | {
3424
+ status?: 'expired';
3425
+ message?: string;
3426
+ }));
3427
+
3428
+ export type PatchV1ConnectTelegramError = ({
3429
+ error?: string;
3430
+ } | unknown);
3431
+
3432
+ export type PutV1AccountsByAccountIdFacebookPageData = {
3433
+ body: {
3434
+ selectedPageId: string;
3435
+ };
3436
+ path: {
3437
+ accountId: string;
3438
+ };
3439
+ };
3440
+
3441
+ export type PutV1AccountsByAccountIdFacebookPageResponse = ({
3442
+ message?: string;
3443
+ account?: SocialAccount;
3444
+ });
3445
+
3446
+ export type PutV1AccountsByAccountIdFacebookPageError = (unknown | {
3447
+ error?: string;
3448
+ });
3449
+
3450
+ export type GetV1AccountsByAccountIdLinkedinOrganizationsData = {
3451
+ path: {
3452
+ accountId: string;
3453
+ };
3454
+ };
3455
+
3456
+ export type GetV1AccountsByAccountIdLinkedinOrganizationsResponse = ({
3457
+ organizations?: Array<{
3458
+ id?: string;
3459
+ name?: string;
3460
+ vanityName?: string;
3461
+ localizedName?: string;
3462
+ }>;
3463
+ });
3464
+
3465
+ export type GetV1AccountsByAccountIdLinkedinOrganizationsError = ({
3466
+ error?: string;
3467
+ } | unknown);
3468
+
3469
+ export type GetV1AccountsByAccountIdLinkedinAggregateAnalyticsData = {
3470
+ path: {
3471
+ /**
3472
+ * The ID of the LinkedIn personal account
3473
+ */
3474
+ accountId: string;
3475
+ };
3476
+ query?: {
3477
+ /**
3478
+ * Type of aggregation for the analytics data.
3479
+ * - `TOTAL` (default): Returns single totals for each metric
3480
+ * - `DAILY`: Returns daily breakdown of metrics
3481
+ *
3482
+ * Note: `MEMBERS_REACHED` metric is not available with `DAILY` aggregation.
3483
+ *
3484
+ */
3485
+ aggregation?: 'TOTAL' | 'DAILY';
3486
+ /**
3487
+ * End date for analytics data in YYYY-MM-DD format (exclusive).
3488
+ * If provided without startDate, startDate defaults to 30 days before endDate.
3489
+ *
3490
+ */
3491
+ endDate?: string;
3492
+ /**
3493
+ * Comma-separated list of metrics to fetch. If omitted, fetches all available metrics.
3494
+ * Valid values: IMPRESSION, MEMBERS_REACHED, REACTION, COMMENT, RESHARE
3495
+ *
3496
+ */
3497
+ metrics?: string;
3498
+ /**
3499
+ * Start date for analytics data in YYYY-MM-DD format.
3500
+ * If provided without endDate, endDate defaults to today.
3501
+ * If omitted entirely, returns lifetime analytics.
3502
+ *
3503
+ */
3504
+ startDate?: string;
3505
+ };
3506
+ };
3507
+
3508
+ export type GetV1AccountsByAccountIdLinkedinAggregateAnalyticsResponse = ((LinkedInAggregateAnalyticsTotalResponse | LinkedInAggregateAnalyticsDailyResponse));
3509
+
3510
+ export type GetV1AccountsByAccountIdLinkedinAggregateAnalyticsError = ({
3511
+ error?: string;
3512
+ code?: string;
3513
+ validOptions?: Array<(string)>;
3514
+ } | {
3515
+ error?: string;
3516
+ } | {
3517
+ error?: string;
3518
+ code?: string;
3519
+ } | {
3520
+ error?: string;
3521
+ code?: string;
3522
+ requiredScope?: string;
3523
+ action?: string;
3524
+ } | unknown);
3525
+
3526
+ export type GetV1AccountsByAccountIdLinkedinPostAnalyticsData = {
3527
+ path: {
3528
+ /**
3529
+ * The ID of the LinkedIn account
3530
+ */
3531
+ accountId: string;
3532
+ };
3533
+ query: {
3534
+ /**
3535
+ * The LinkedIn post URN
3536
+ */
3537
+ urn: string;
3538
+ };
3539
+ };
3540
+
3541
+ export type GetV1AccountsByAccountIdLinkedinPostAnalyticsResponse = ({
3542
+ accountId?: string;
3543
+ platform?: string;
3544
+ accountType?: 'personal' | 'organization';
3545
+ username?: string;
3546
+ postUrn?: string;
3547
+ analytics?: {
3548
+ /**
3549
+ * Times the post was shown
3550
+ */
3551
+ impressions?: number;
3552
+ /**
3553
+ * Unique members who saw the post
3554
+ */
3555
+ reach?: number;
3556
+ /**
3557
+ * Reactions on the post
3558
+ */
3559
+ likes?: number;
3560
+ /**
3561
+ * Comments on the post
3562
+ */
3563
+ comments?: number;
3564
+ /**
3565
+ * Reshares of the post
3566
+ */
3567
+ shares?: number;
3568
+ /**
3569
+ * Clicks on the post (organization accounts only)
3570
+ */
3571
+ clicks?: number;
3572
+ /**
3573
+ * Video views (video posts only)
3574
+ */
3575
+ views?: number;
3576
+ /**
3577
+ * Engagement rate as percentage
3578
+ */
3579
+ engagementRate?: number;
3580
+ };
3581
+ lastUpdated?: string;
3582
+ });
3583
+
3584
+ export type GetV1AccountsByAccountIdLinkedinPostAnalyticsError = ({
3585
+ error?: string;
3586
+ code?: 'missing_urn' | 'invalid_urn' | 'invalid_platform';
3587
+ } | {
3588
+ error?: string;
3589
+ } | unknown | {
3590
+ error?: string;
3591
+ code?: string;
3592
+ requiredScope?: string;
3593
+ action?: string;
3594
+ } | {
3595
+ error?: string;
3596
+ code?: string;
3597
+ });
3598
+
3599
+ export type PutV1AccountsByAccountIdLinkedinOrganizationData = {
3600
+ body: {
3601
+ accountType: 'personal' | 'organization';
3602
+ selectedOrganization?: {
3603
+ [key: string]: unknown;
3604
+ };
3605
+ };
3606
+ path: {
3607
+ accountId: string;
3608
+ };
3609
+ };
3610
+
3611
+ export type PutV1AccountsByAccountIdLinkedinOrganizationResponse = ({
3612
+ message?: string;
3613
+ account?: SocialAccount;
3614
+ });
3615
+
3616
+ export type PutV1AccountsByAccountIdLinkedinOrganizationError = (unknown | {
3617
+ error?: string;
3618
+ });
3619
+
3620
+ export type GetV1AccountsByAccountIdLinkedinMentionsData = {
3621
+ path: {
3622
+ /**
3623
+ * The LinkedIn account ID
3624
+ */
3625
+ accountId: string;
3626
+ };
3627
+ query: {
3628
+ /**
3629
+ * The exact display name as shown on LinkedIn.
3630
+ * - **Person mentions:** Required for clickable mentions. If not provided, a name is derived from the vanity URL which may not match exactly.
3631
+ * - **Organization mentions:** Optional. If not provided, the company name is automatically retrieved from LinkedIn.
3632
+ *
3633
+ */
3634
+ displayName?: string;
3635
+ /**
3636
+ * LinkedIn profile URL, company URL, or vanity name.
3637
+ * - Person: `miquelpalet`, `linkedin.com/in/miquelpalet`
3638
+ * - Organization: `company/microsoft`, `linkedin.com/company/microsoft`
3639
+ *
3640
+ */
3641
+ url: string;
3642
+ };
3643
+ };
3644
+
3645
+ export type GetV1AccountsByAccountIdLinkedinMentionsResponse = ({
3646
+ /**
3647
+ * The LinkedIn URN (person or organization)
3648
+ */
3649
+ urn?: string;
3650
+ /**
3651
+ * The type of entity (person or organization)
3652
+ */
3653
+ type?: 'person' | 'organization';
3654
+ /**
3655
+ * Display name (provided, from API, or derived from vanity URL)
3656
+ */
3657
+ displayName?: string;
3658
+ /**
3659
+ * Ready-to-use mention format for post content
3660
+ */
3661
+ mentionFormat?: string;
3662
+ /**
3663
+ * The vanity name/slug (only for organization mentions)
3664
+ */
3665
+ vanityName?: string;
3666
+ /**
3667
+ * Warning about clickable mentions (only present for person mentions if displayName was not provided)
3668
+ */
3669
+ warning?: string;
3670
+ });
3671
+
3672
+ export type GetV1AccountsByAccountIdLinkedinMentionsError = ({
3673
+ error?: string;
3674
+ });
3675
+
3676
+ export type GetV1AccountsByAccountIdPinterestBoardsData = {
3677
+ path: {
3678
+ accountId: string;
3679
+ };
3680
+ };
3681
+
3682
+ export type GetV1AccountsByAccountIdPinterestBoardsResponse = ({
3683
+ boards?: Array<{
3684
+ id?: string;
3685
+ name?: string;
3686
+ description?: string;
3687
+ privacy?: string;
3688
+ }>;
3689
+ });
3690
+
3691
+ export type GetV1AccountsByAccountIdPinterestBoardsError = (unknown | {
3692
+ error?: string;
3693
+ });
3694
+
3695
+ export type PutV1AccountsByAccountIdPinterestBoardsData = {
3696
+ body: {
3697
+ defaultBoardId: string;
3698
+ defaultBoardName?: string;
3699
+ };
3700
+ path: {
3701
+ accountId: string;
3702
+ };
3703
+ };
3704
+
3705
+ export type PutV1AccountsByAccountIdPinterestBoardsResponse = ({
3706
+ message?: string;
3707
+ account?: SocialAccount;
3708
+ });
3709
+
3710
+ export type PutV1AccountsByAccountIdPinterestBoardsError = (unknown | {
3711
+ error?: string;
3712
+ });
3713
+
3714
+ export type GetV1AccountsByAccountIdRedditSubredditsData = {
3715
+ path: {
3716
+ accountId: string;
3717
+ };
3718
+ };
3719
+
3720
+ export type GetV1AccountsByAccountIdRedditSubredditsResponse = ({
3721
+ subreddits?: Array<{
3722
+ name?: string;
3723
+ displayName?: string;
3724
+ subscribers?: number;
3725
+ public_description?: string;
3726
+ }>;
3727
+ });
3728
+
3729
+ export type GetV1AccountsByAccountIdRedditSubredditsError = (unknown | {
3730
+ error?: string;
3731
+ });
3732
+
3733
+ export type PutV1AccountsByAccountIdRedditSubredditsData = {
3734
+ body: {
3735
+ defaultSubreddit: string;
3736
+ };
3737
+ path: {
3738
+ accountId: string;
3739
+ };
3740
+ };
3741
+
3742
+ export type PutV1AccountsByAccountIdRedditSubredditsResponse = ({
3743
+ message?: string;
3744
+ account?: SocialAccount;
3745
+ });
3746
+
3747
+ export type PutV1AccountsByAccountIdRedditSubredditsError = (unknown | {
3748
+ error?: string;
3749
+ });
3750
+
3751
+ export type GetV1QueueSlotsData = {
3752
+ query: {
3753
+ /**
3754
+ * Set to 'true' to list all queues for the profile
3755
+ */
3756
+ all?: 'true';
3757
+ /**
3758
+ * Profile ID to get queues for
3759
+ */
3760
+ profileId: string;
3761
+ /**
3762
+ * Specific queue ID to retrieve (optional)
3763
+ */
3764
+ queueId?: string;
3765
+ };
3766
+ };
3767
+
3768
+ export type GetV1QueueSlotsResponse = (({
3769
+ exists?: boolean;
3770
+ schedule?: QueueSchedule;
3771
+ nextSlots?: Array<(string)>;
3772
+ } | {
3773
+ queues?: Array<QueueSchedule>;
3774
+ count?: number;
3775
+ }));
3776
+
3777
+ export type GetV1QueueSlotsError = (unknown | {
3778
+ error?: string;
3779
+ });
3780
+
3781
+ export type PostV1QueueSlotsData = {
3782
+ body: {
3783
+ /**
3784
+ * Profile ID
3785
+ */
3786
+ profileId: string;
3787
+ /**
3788
+ * Queue name (e.g., Evening Posts)
3789
+ */
3790
+ name: string;
3791
+ /**
3792
+ * IANA timezone
3793
+ */
3794
+ timezone: string;
3795
+ slots: Array<QueueSlot>;
3796
+ active?: boolean;
3797
+ };
3798
+ };
3799
+
3800
+ export type PostV1QueueSlotsResponse = ({
3801
+ success?: boolean;
3802
+ schedule?: QueueSchedule;
3803
+ nextSlots?: Array<(string)>;
3804
+ });
3805
+
3806
+ export type PostV1QueueSlotsError = (unknown | {
3807
+ error?: string;
3808
+ });
3809
+
3810
+ export type PutV1QueueSlotsData = {
3811
+ body: {
3812
+ profileId: string;
3813
+ /**
3814
+ * Queue ID to update (optional)
3815
+ */
3816
+ queueId?: string;
3817
+ /**
3818
+ * Queue name
3819
+ */
3820
+ name?: string;
3821
+ timezone: string;
3822
+ slots: Array<QueueSlot>;
3823
+ active?: boolean;
3824
+ /**
3825
+ * Make this queue the default
3826
+ */
3827
+ setAsDefault?: boolean;
3828
+ /**
3829
+ * Whether to reschedule existing queued posts to match new slots
3830
+ */
3831
+ reshuffleExisting?: boolean;
3832
+ };
3833
+ };
3834
+
3835
+ export type PutV1QueueSlotsResponse = ({
3836
+ success?: boolean;
3837
+ schedule?: QueueSchedule;
3838
+ nextSlots?: Array<(string)>;
3839
+ reshuffledCount?: number;
3840
+ });
3841
+
3842
+ export type PutV1QueueSlotsError = (unknown | {
3843
+ error?: string;
3844
+ });
3845
+
3846
+ export type DeleteV1QueueSlotsData = {
3847
+ query: {
3848
+ profileId: string;
3849
+ /**
3850
+ * Queue ID to delete
3851
+ */
3852
+ queueId: string;
3853
+ };
3854
+ };
3855
+
3856
+ export type DeleteV1QueueSlotsResponse = ({
3857
+ success?: boolean;
3858
+ deleted?: boolean;
3859
+ });
3860
+
3861
+ export type DeleteV1QueueSlotsError = (unknown | {
3862
+ error?: string;
3863
+ });
3864
+
3865
+ export type GetV1QueuePreviewData = {
3866
+ query: {
3867
+ count?: number;
3868
+ profileId: string;
3869
+ };
3870
+ };
3871
+
3872
+ export type GetV1QueuePreviewResponse = ({
3873
+ profileId?: string;
3874
+ count?: number;
3875
+ slots?: Array<(string)>;
3876
+ });
3877
+
3878
+ export type GetV1QueuePreviewError = (unknown | {
3879
+ error?: string;
3880
+ });
3881
+
3882
+ export type GetV1QueueNextSlotData = {
3883
+ query: {
3884
+ profileId: string;
3885
+ /**
3886
+ * Specific queue ID (optional, defaults to profile's default queue)
3887
+ */
3888
+ queueId?: string;
3889
+ };
3890
+ };
3891
+
3892
+ export type GetV1QueueNextSlotResponse = ({
3893
+ profileId?: string;
3894
+ nextSlot?: string;
3895
+ timezone?: string;
3896
+ /**
3897
+ * Queue ID this slot belongs to
3898
+ */
3899
+ queueId?: string;
3900
+ /**
3901
+ * Queue name
3902
+ */
3903
+ queueName?: string;
3904
+ });
3905
+
3906
+ export type GetV1QueueNextSlotError = (unknown | {
3907
+ error?: string;
3908
+ });
3909
+
3910
+ export type GetV1WebhooksSettingsResponse = ({
3911
+ webhooks?: Array<Webhook>;
3912
+ });
3913
+
3914
+ export type GetV1WebhooksSettingsError = ({
3915
+ error?: string;
3916
+ });
3917
+
3918
+ export type PostV1WebhooksSettingsData = {
3919
+ body: {
3920
+ /**
3921
+ * Webhook name (max 50 characters)
3922
+ */
3923
+ name?: string;
3924
+ /**
3925
+ * Webhook endpoint URL (must be HTTPS in production)
3926
+ */
3927
+ url?: string;
3928
+ /**
3929
+ * Secret key for HMAC-SHA256 signature verification
3930
+ */
3931
+ secret?: string;
3932
+ /**
3933
+ * Events to subscribe to
3934
+ */
3935
+ events?: Array<('post.scheduled' | 'post.published' | 'post.failed' | 'post.partial' | 'account.disconnected')>;
3936
+ /**
3937
+ * Enable or disable webhook delivery
3938
+ */
3939
+ isActive?: boolean;
3940
+ /**
3941
+ * Custom headers to include in webhook requests
3942
+ */
3943
+ customHeaders?: {
3944
+ [key: string]: (string);
3945
+ };
3946
+ };
3947
+ };
3948
+
3949
+ export type PostV1WebhooksSettingsResponse = ({
3950
+ success?: boolean;
3951
+ webhook?: Webhook;
3952
+ });
3953
+
3954
+ export type PostV1WebhooksSettingsError = (unknown | {
3955
+ error?: string;
3956
+ });
3957
+
3958
+ export type PutV1WebhooksSettingsData = {
3959
+ body: {
3960
+ /**
3961
+ * Webhook ID to update (required)
3962
+ */
3963
+ _id: string;
3964
+ /**
3965
+ * Webhook name (max 50 characters)
3966
+ */
3967
+ name?: string;
3968
+ /**
3969
+ * Webhook endpoint URL (must be HTTPS in production)
3970
+ */
3971
+ url?: string;
3972
+ /**
3973
+ * Secret key for HMAC-SHA256 signature verification
3974
+ */
3975
+ secret?: string;
3976
+ /**
3977
+ * Events to subscribe to
3978
+ */
3979
+ events?: Array<('post.scheduled' | 'post.published' | 'post.failed' | 'post.partial' | 'account.disconnected')>;
3980
+ /**
3981
+ * Enable or disable webhook delivery
3982
+ */
3983
+ isActive?: boolean;
3984
+ /**
3985
+ * Custom headers to include in webhook requests
3986
+ */
3987
+ customHeaders?: {
3988
+ [key: string]: (string);
3989
+ };
3990
+ };
3991
+ };
3992
+
3993
+ export type PutV1WebhooksSettingsResponse = ({
3994
+ success?: boolean;
3995
+ webhook?: Webhook;
3996
+ });
3997
+
3998
+ export type PutV1WebhooksSettingsError = (unknown | {
3999
+ error?: string;
4000
+ });
4001
+
4002
+ export type DeleteV1WebhooksSettingsData = {
4003
+ query: {
4004
+ /**
4005
+ * Webhook ID to delete
4006
+ */
4007
+ id: string;
4008
+ };
4009
+ };
4010
+
4011
+ export type DeleteV1WebhooksSettingsResponse = ({
4012
+ success?: boolean;
4013
+ });
4014
+
4015
+ export type DeleteV1WebhooksSettingsError = (unknown | {
4016
+ error?: string;
4017
+ });
4018
+
4019
+ export type PostV1WebhooksTestData = {
4020
+ body: {
4021
+ /**
4022
+ * ID of the webhook to test
4023
+ */
4024
+ webhookId: string;
4025
+ };
4026
+ };
4027
+
4028
+ export type PostV1WebhooksTestResponse = ({
4029
+ success?: boolean;
4030
+ message?: string;
4031
+ });
4032
+
4033
+ export type PostV1WebhooksTestError = (unknown | {
4034
+ error?: string;
4035
+ } | {
4036
+ success?: boolean;
4037
+ message?: string;
4038
+ });
4039
+
4040
+ export type GetV1WebhooksLogsData = {
4041
+ query?: {
4042
+ /**
4043
+ * Filter by event type
4044
+ */
4045
+ event?: 'post.scheduled' | 'post.published' | 'post.failed' | 'post.partial' | 'account.disconnected' | 'webhook.test';
4046
+ /**
4047
+ * Maximum number of logs to return (max 100)
4048
+ */
4049
+ limit?: number;
4050
+ /**
4051
+ * Filter by delivery status
4052
+ */
4053
+ status?: 'success' | 'failed';
4054
+ /**
4055
+ * Filter by webhook ID
4056
+ */
4057
+ webhookId?: string;
4058
+ };
4059
+ };
4060
+
4061
+ export type GetV1WebhooksLogsResponse = ({
4062
+ logs?: Array<WebhookLog>;
4063
+ });
4064
+
4065
+ export type GetV1WebhooksLogsError = ({
4066
+ error?: string;
4067
+ });
4068
+
4069
+ export type GetV1LogsData = {
4070
+ query?: {
4071
+ /**
4072
+ * Filter by action type
4073
+ */
4074
+ action?: 'publish' | 'retry' | 'media_upload' | 'rate_limit_pause' | 'token_refresh' | 'cancelled' | 'all';
4075
+ /**
4076
+ * Number of days to look back (max 7)
4077
+ */
4078
+ days?: number;
4079
+ /**
4080
+ * Maximum number of logs to return (max 100)
4081
+ */
4082
+ limit?: number;
4083
+ /**
4084
+ * Filter by platform
4085
+ */
4086
+ platform?: 'tiktok' | 'instagram' | 'facebook' | 'youtube' | 'linkedin' | 'twitter' | 'threads' | 'pinterest' | 'reddit' | 'bluesky' | 'googlebusiness' | 'telegram' | 'snapchat' | 'all';
4087
+ /**
4088
+ * Number of logs to skip (for pagination)
4089
+ */
4090
+ skip?: number;
4091
+ /**
4092
+ * Filter by log status
4093
+ */
4094
+ status?: 'success' | 'failed' | 'pending' | 'skipped' | 'all';
4095
+ };
4096
+ };
4097
+
4098
+ export type GetV1LogsResponse = ({
4099
+ logs?: Array<PostLog>;
4100
+ pagination?: {
4101
+ /**
4102
+ * Total number of logs matching the query
4103
+ */
4104
+ total?: number;
4105
+ limit?: number;
4106
+ skip?: number;
4107
+ /**
4108
+ * Total number of pages
4109
+ */
4110
+ pages?: number;
4111
+ hasMore?: boolean;
4112
+ };
4113
+ });
4114
+
4115
+ export type GetV1LogsError = ({
4116
+ error?: string;
4117
+ });
4118
+
4119
+ export type GetV1LogsByLogIdData = {
4120
+ path: {
4121
+ /**
4122
+ * The log entry ID
4123
+ */
4124
+ logId: string;
4125
+ };
4126
+ };
4127
+
4128
+ export type GetV1LogsByLogIdResponse = ({
4129
+ log?: PostLogDetail;
4130
+ });
4131
+
4132
+ export type GetV1LogsByLogIdError = ({
4133
+ error?: string;
4134
+ } | unknown);
4135
+
4136
+ export type GetV1PostsByPostIdLogsData = {
4137
+ path: {
4138
+ /**
4139
+ * The post ID
4140
+ */
4141
+ postId: string;
4142
+ };
4143
+ query?: {
4144
+ /**
4145
+ * Maximum number of logs to return (max 100)
4146
+ */
4147
+ limit?: number;
4148
+ };
4149
+ };
4150
+
4151
+ export type GetV1PostsByPostIdLogsResponse = ({
4152
+ logs?: Array<PostLog>;
4153
+ /**
4154
+ * Number of logs returned
4155
+ */
4156
+ count?: number;
4157
+ postId?: string;
4158
+ });
4159
+
4160
+ export type GetV1PostsByPostIdLogsError = ({
4161
+ error?: string;
4162
+ } | unknown);