stophy 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,805 @@
1
+ import { Client } from '@hey-api/client-fetch';
2
+
3
+ type ErrorResponse = {
4
+ /**
5
+ * Always false for error responses.
6
+ */
7
+ success: false;
8
+ /**
9
+ * Machine-readable error code.
10
+ */
11
+ code?: 'UNAUTHORIZED' | 'INSUFFICIENT_CREDITS' | 'BAD_REQUEST' | 'INVALID_INPUT' | 'NOT_FOUND' | 'CONCURRENCY_LIMITED' | 'INTERNAL_ERROR';
12
+ /**
13
+ * Human-readable error message.
14
+ */
15
+ error: string;
16
+ /**
17
+ * Optional additional context, present on validation errors.
18
+ */
19
+ details?: unknown;
20
+ };
21
+ type Thumbnail = {
22
+ url: string;
23
+ width: number;
24
+ height: number;
25
+ };
26
+ type EmptyState = {
27
+ code: string;
28
+ message: string;
29
+ };
30
+ type TranscriptLanguage = {
31
+ code: string | null;
32
+ name: string | null;
33
+ isAutoGenerated: boolean;
34
+ };
35
+ type TranscriptSegment = {
36
+ start: number;
37
+ duration: number;
38
+ text: string;
39
+ };
40
+ type TranscriptResult = {
41
+ language: TranscriptLanguage;
42
+ segments: Array<TranscriptSegment>;
43
+ text: string;
44
+ empty?: EmptyState;
45
+ };
46
+ type VideoDetails = {
47
+ id: string;
48
+ type?: 'video';
49
+ videoUrl: string;
50
+ title: string | null;
51
+ author?: string | null;
52
+ authorId?: string | null;
53
+ category?: string | null;
54
+ description?: string | null;
55
+ durationSec?: number | null;
56
+ durationText?: string | null;
57
+ isLive?: boolean;
58
+ likeCount?: number | null;
59
+ likeCountText?: string | null;
60
+ publishedAt?: string | null;
61
+ tags?: Array<string>;
62
+ viewCount?: number | null;
63
+ viewCountText?: string | null;
64
+ thumbnails: Array<Thumbnail>;
65
+ };
66
+ type RelatedVideo = {
67
+ id: string;
68
+ type?: 'video';
69
+ videoUrl: string;
70
+ title?: string | null;
71
+ author?: string | null;
72
+ authorId?: string | null;
73
+ durationSec?: number | null;
74
+ durationText?: string | null;
75
+ publishedAt?: string | null;
76
+ publishedAtText?: string | null;
77
+ viewCount?: number | null;
78
+ viewCountText?: string | null;
79
+ thumbnails: Array<Thumbnail>;
80
+ };
81
+ type VideoDetailsData = {
82
+ video: VideoDetails;
83
+ related: Array<RelatedVideo>;
84
+ };
85
+ type Comment = {
86
+ id: string | null;
87
+ text: string | null;
88
+ author: string | null;
89
+ authorId: string | null;
90
+ authorThumbnail?: string | null;
91
+ hasChannelOwnerReplied: boolean;
92
+ isChannelOwner: boolean;
93
+ isHearted: boolean;
94
+ isPinned: boolean;
95
+ isVerified: boolean;
96
+ publishedAt?: string | null;
97
+ publishedAtText?: string | null;
98
+ likeCount?: number | null;
99
+ likeCountText?: string | null;
100
+ replyCount?: number | null;
101
+ replyCountText?: string | null;
102
+ repliesToken?: string | null;
103
+ };
104
+ type CommentsData = {
105
+ items: Array<Comment>;
106
+ continuationToken: string | null;
107
+ empty?: EmptyState;
108
+ };
109
+ type LiveChatMessage = {
110
+ id: string;
111
+ text: string;
112
+ author?: string | null;
113
+ authorId?: string | null;
114
+ timestampUsec?: string | null;
115
+ isOwner: boolean;
116
+ isModerator: boolean;
117
+ isVerified: boolean;
118
+ superChatAmount?: string | null;
119
+ superChatCurrency?: string | null;
120
+ };
121
+ type LiveChatData = {
122
+ status: string;
123
+ isLive: boolean;
124
+ concurrentViewers?: number | null;
125
+ pollIntervalMs?: number | null;
126
+ messages: Array<LiveChatMessage>;
127
+ continuationToken: string | null;
128
+ };
129
+ /**
130
+ * Shape depends on the request `type`: details, transcript, comments/replies, or livechat.
131
+ */
132
+ type VideoData = VideoDetailsData | TranscriptResult | CommentsData | LiveChatData;
133
+ type SearchVideo = {
134
+ type: 'video';
135
+ id: string;
136
+ videoUrl: string;
137
+ title: string;
138
+ author?: string | null;
139
+ authorId?: string | null;
140
+ description?: string | null;
141
+ duration?: string | null;
142
+ durationSec?: number | null;
143
+ durationText?: string | null;
144
+ isLive?: boolean;
145
+ isUpcoming?: boolean;
146
+ isVerified?: boolean;
147
+ viewCount?: number | null;
148
+ viewCountText?: string | null;
149
+ publishedAt?: string | null;
150
+ publishedAtText?: string | null;
151
+ thumbnails: Array<Thumbnail>;
152
+ };
153
+ type SearchShort = {
154
+ type: 'short';
155
+ id: string;
156
+ shortUrl: string;
157
+ title: string;
158
+ author?: string | null;
159
+ authorId?: string | null;
160
+ description?: string | null;
161
+ duration?: string | null;
162
+ durationSec?: number | null;
163
+ durationText?: string | null;
164
+ viewCount?: number | null;
165
+ viewCountText?: string | null;
166
+ publishedAt?: string | null;
167
+ publishedAtText?: string | null;
168
+ thumbnails: Array<Thumbnail>;
169
+ };
170
+ type SearchPlaylist = {
171
+ type: 'playlist';
172
+ id: string;
173
+ playlistUrl: string;
174
+ title: string;
175
+ author?: string | null;
176
+ authorId?: string | null;
177
+ videoCount?: number | null;
178
+ videoCountText?: string | null;
179
+ thumbnails: Array<Thumbnail>;
180
+ };
181
+ type SearchChannel = {
182
+ type: 'channel';
183
+ id: string;
184
+ channelUrl: string;
185
+ name: string;
186
+ handle?: string | null;
187
+ description?: string | null;
188
+ subscriberCount?: number | null;
189
+ subscriberCountText?: string | null;
190
+ isVerified?: boolean;
191
+ thumbnails: Array<Thumbnail>;
192
+ };
193
+ type SearchItem = ({
194
+ type?: 'video';
195
+ } & SearchVideo) | ({
196
+ type?: 'short';
197
+ } & SearchShort) | ({
198
+ type?: 'playlist';
199
+ } & SearchPlaylist) | ({
200
+ type?: 'channel';
201
+ } & SearchChannel);
202
+ type SearchData = {
203
+ items: Array<SearchItem>;
204
+ continuationToken: string | null;
205
+ estimatedResults?: number;
206
+ empty?: EmptyState;
207
+ };
208
+ type ChannelLink = {
209
+ title: string;
210
+ url: string;
211
+ };
212
+ type ChannelProfile = {
213
+ id: string | null;
214
+ name: string | null;
215
+ handle: string | null;
216
+ channelUrl: string | null;
217
+ description?: string | null;
218
+ subscriberCount?: number | null;
219
+ subscriberCountText?: string | null;
220
+ videoCount?: number | null;
221
+ videoCountText?: string | null;
222
+ viewCount?: number | null;
223
+ viewCountText?: string | null;
224
+ isVerified: boolean;
225
+ country?: string | null;
226
+ joinedDate?: string | null;
227
+ thumbnails: Array<Thumbnail>;
228
+ banners: Array<Thumbnail>;
229
+ links?: Array<ChannelLink> | null;
230
+ };
231
+ type ContentItem = {
232
+ id: string;
233
+ type?: string;
234
+ title?: string | null;
235
+ videoUrl?: string;
236
+ shortUrl?: string;
237
+ playlistUrl?: string;
238
+ author?: string | null;
239
+ authorId?: string | null;
240
+ durationSec?: number | null;
241
+ durationText?: string | null;
242
+ viewCount?: number | null;
243
+ viewCountText?: string | null;
244
+ publishedAt?: string | null;
245
+ publishedAtText?: string | null;
246
+ thumbnails: Array<Thumbnail>;
247
+ };
248
+ type ChannelData = {
249
+ channel: ChannelProfile | null;
250
+ tab?: string | null;
251
+ items?: Array<ContentItem>;
252
+ continuationToken?: string | null;
253
+ empty?: EmptyState;
254
+ };
255
+ type PlaylistMeta = {
256
+ id: string;
257
+ type?: 'playlist';
258
+ playlistUrl: string;
259
+ title?: string | null;
260
+ author?: string | null;
261
+ authorId?: string | null;
262
+ description?: string | null;
263
+ videoCount?: string | null;
264
+ thumbnails: Array<Thumbnail>;
265
+ };
266
+ type PlaylistItem = {
267
+ id: string;
268
+ type?: 'video';
269
+ videoUrl: string;
270
+ title?: string | null;
271
+ author?: string | null;
272
+ authorId?: string | null;
273
+ durationSec?: number | null;
274
+ durationText?: string | null;
275
+ index?: number | null;
276
+ isLive?: boolean;
277
+ isPlayable?: boolean;
278
+ isUpcoming?: boolean;
279
+ upcomingAt?: string | null;
280
+ viewCount?: number | null;
281
+ viewCountText?: string | null;
282
+ publishedAt?: string | null;
283
+ publishedAtText?: string | null;
284
+ thumbnails: Array<Thumbnail>;
285
+ };
286
+ type PlaylistData = {
287
+ playlist: PlaylistMeta | null;
288
+ items: Array<PlaylistItem>;
289
+ continuationToken: string | null;
290
+ empty?: EmptyState;
291
+ };
292
+ type SuggestData = {
293
+ q: string;
294
+ hl: string;
295
+ gl: string;
296
+ suggestions: Array<string>;
297
+ };
298
+ type CreditsData = {
299
+ credits: number;
300
+ };
301
+ type LogEntry = {
302
+ id: string;
303
+ userId?: string;
304
+ apiKeyId?: string | null;
305
+ apiKeyName?: string | null;
306
+ endpoint: string;
307
+ method: string;
308
+ status: number;
309
+ credits: number;
310
+ durationMs?: number | null;
311
+ response?: string | null;
312
+ createdAt: string;
313
+ };
314
+ type LogsData = {
315
+ logs: Array<LogEntry>;
316
+ total: number;
317
+ page: number;
318
+ pageSize: number;
319
+ totalPages: number;
320
+ endpoints: Array<string>;
321
+ };
322
+ type UsageItem = {
323
+ date: string;
324
+ credits: number;
325
+ requests: number;
326
+ };
327
+ type UsageData = {
328
+ items: Array<UsageItem>;
329
+ };
330
+ type GetVideoData = {
331
+ body: {
332
+ /**
333
+ * The type of data to retrieve.
334
+ */
335
+ type: 'details' | 'transcript' | 'comments' | 'replies' | 'livechat';
336
+ /**
337
+ * Full YouTube video URL. Not required when type is replies.
338
+ */
339
+ videoUrl: string;
340
+ /**
341
+ * Comment sort order. Only applies when type is comments.
342
+ */
343
+ sortBy?: 'latest' | 'top';
344
+ /**
345
+ * Live chat mode. Only applies when type is livechat: 'top' = Top chat (moderated, default), 'live' = all messages. Applied on the first call; later polls keep the chosen mode.
346
+ */
347
+ chatType?: 'top' | 'live';
348
+ /**
349
+ * Pagination token. Required when type is replies (use the repliesToken from a comment item); for livechat, pass the continuationToken from a previous livechat response to poll for new messages.
350
+ */
351
+ continuationToken?: string;
352
+ };
353
+ path?: never;
354
+ query?: never;
355
+ url: '/v1/video';
356
+ };
357
+ type GetVideoErrors = {
358
+ /**
359
+ * Validation error
360
+ */
361
+ 400: ErrorResponse;
362
+ /**
363
+ * Invalid or missing API key
364
+ */
365
+ 401: ErrorResponse;
366
+ /**
367
+ * Insufficient credits
368
+ */
369
+ 402: ErrorResponse;
370
+ /**
371
+ * Rate limited
372
+ */
373
+ 429: ErrorResponse;
374
+ /**
375
+ * Internal error
376
+ */
377
+ 500: ErrorResponse;
378
+ };
379
+ type GetVideoError = GetVideoErrors[keyof GetVideoErrors];
380
+ type GetVideoResponses = {
381
+ /**
382
+ * Successful response
383
+ */
384
+ 200: {
385
+ success: true;
386
+ requestId: string;
387
+ data: VideoData;
388
+ cacheState: 'hit' | 'miss';
389
+ creditsUsed: number;
390
+ creditsRemaining: number;
391
+ };
392
+ };
393
+ type GetVideoResponse = GetVideoResponses[keyof GetVideoResponses];
394
+ type SearchVideosData = {
395
+ body: {
396
+ /**
397
+ * Search query.
398
+ */
399
+ q: string;
400
+ /**
401
+ * Filter by content type.
402
+ */
403
+ type?: 'video' | 'short' | 'channel' | 'playlist' | 'movie';
404
+ /**
405
+ * Sort order. Defaults to relevance.
406
+ */
407
+ sortBy?: 'relevance' | 'popularity' | 'date' | 'rating';
408
+ /**
409
+ * Filter by upload date.
410
+ */
411
+ uploadDate?: 'today' | 'week' | 'month' | 'year';
412
+ /**
413
+ * Duration filter. Not applicable when type is short.
414
+ */
415
+ duration?: 'short' | 'medium' | 'long';
416
+ /**
417
+ * Filter by video features.
418
+ */
419
+ features?: Array<'live' | '4k' | 'hd' | 'subtitles' | 'creativeCommons' | '360' | 'vr180' | '3d' | 'hdr' | 'location' | 'purchased'>;
420
+ /**
421
+ * Token from a previous response to fetch the next page.
422
+ */
423
+ continuationToken?: string;
424
+ };
425
+ path?: never;
426
+ query?: never;
427
+ url: '/v1/search';
428
+ };
429
+ type SearchVideosErrors = {
430
+ /**
431
+ * Validation error
432
+ */
433
+ 400: ErrorResponse;
434
+ /**
435
+ * Unauthorized
436
+ */
437
+ 401: ErrorResponse;
438
+ /**
439
+ * Insufficient credits
440
+ */
441
+ 402: ErrorResponse;
442
+ /**
443
+ * Rate limited
444
+ */
445
+ 429: ErrorResponse;
446
+ /**
447
+ * Internal error
448
+ */
449
+ 500: ErrorResponse;
450
+ };
451
+ type SearchVideosError = SearchVideosErrors[keyof SearchVideosErrors];
452
+ type SearchVideosResponses = {
453
+ /**
454
+ * Search results
455
+ */
456
+ 200: {
457
+ success: true;
458
+ requestId: string;
459
+ data: SearchData;
460
+ cacheState: 'hit' | 'miss';
461
+ creditsUsed: number;
462
+ creditsRemaining: number;
463
+ };
464
+ };
465
+ type SearchVideosResponse = SearchVideosResponses[keyof SearchVideosResponses];
466
+ type GetChannelData = {
467
+ body: {
468
+ /**
469
+ * Full YouTube channel URL, e.g. https://www.youtube.com/@mkbhd.
470
+ */
471
+ channelUrl: string;
472
+ /**
473
+ * Content tab to fetch. Defaults to video.
474
+ */
475
+ tab?: 'video' | 'short' | 'playlist' | 'about';
476
+ /**
477
+ * Token from a previous response to fetch the next page.
478
+ */
479
+ continuationToken?: string;
480
+ /**
481
+ * Sort order for the selected tab.
482
+ */
483
+ sortBy?: 'latest' | 'popular' | 'oldest';
484
+ };
485
+ path?: never;
486
+ query?: never;
487
+ url: '/v1/channel';
488
+ };
489
+ type GetChannelErrors = {
490
+ /**
491
+ * Validation error
492
+ */
493
+ 400: ErrorResponse;
494
+ /**
495
+ * Unauthorized
496
+ */
497
+ 401: ErrorResponse;
498
+ /**
499
+ * Insufficient credits
500
+ */
501
+ 402: ErrorResponse;
502
+ /**
503
+ * Rate limited
504
+ */
505
+ 429: ErrorResponse;
506
+ /**
507
+ * Internal error
508
+ */
509
+ 500: ErrorResponse;
510
+ };
511
+ type GetChannelError = GetChannelErrors[keyof GetChannelErrors];
512
+ type GetChannelResponses = {
513
+ /**
514
+ * Channel data
515
+ */
516
+ 200: {
517
+ success: true;
518
+ requestId: string;
519
+ data: ChannelData;
520
+ cacheState: 'hit' | 'miss';
521
+ creditsUsed: number;
522
+ creditsRemaining: number;
523
+ };
524
+ };
525
+ type GetChannelResponse = GetChannelResponses[keyof GetChannelResponses];
526
+ type GetPlaylistData = {
527
+ body: {
528
+ /**
529
+ * Full YouTube playlist URL.
530
+ */
531
+ playlistUrl: string;
532
+ /**
533
+ * Token from a previous response to fetch the next page.
534
+ */
535
+ continuationToken?: string;
536
+ };
537
+ path?: never;
538
+ query?: never;
539
+ url: '/v1/playlist';
540
+ };
541
+ type GetPlaylistErrors = {
542
+ /**
543
+ * Validation error
544
+ */
545
+ 400: ErrorResponse;
546
+ /**
547
+ * Unauthorized
548
+ */
549
+ 401: ErrorResponse;
550
+ /**
551
+ * Insufficient credits
552
+ */
553
+ 402: ErrorResponse;
554
+ /**
555
+ * Rate limited
556
+ */
557
+ 429: ErrorResponse;
558
+ /**
559
+ * Internal error
560
+ */
561
+ 500: ErrorResponse;
562
+ };
563
+ type GetPlaylistError = GetPlaylistErrors[keyof GetPlaylistErrors];
564
+ type GetPlaylistResponses = {
565
+ /**
566
+ * Playlist items
567
+ */
568
+ 200: {
569
+ success: true;
570
+ requestId: string;
571
+ data: PlaylistData;
572
+ cacheState: 'hit' | 'miss';
573
+ creditsUsed: number;
574
+ creditsRemaining: number;
575
+ };
576
+ };
577
+ type GetPlaylistResponse = GetPlaylistResponses[keyof GetPlaylistResponses];
578
+ type GetSuggestionsData = {
579
+ body?: never;
580
+ path?: never;
581
+ query: {
582
+ /**
583
+ * Search query.
584
+ */
585
+ q: string;
586
+ /**
587
+ * Language code, e.g. en, fr, de. Defaults to en.
588
+ */
589
+ hl?: string;
590
+ /**
591
+ * Country code, e.g. US, GB, DE. Defaults to US.
592
+ */
593
+ gl?: string;
594
+ };
595
+ url: '/v1/suggest';
596
+ };
597
+ type GetSuggestionsErrors = {
598
+ /**
599
+ * Validation error
600
+ */
601
+ 400: ErrorResponse;
602
+ /**
603
+ * Unauthorized
604
+ */
605
+ 401: ErrorResponse;
606
+ /**
607
+ * Rate limited
608
+ */
609
+ 429: ErrorResponse;
610
+ /**
611
+ * Internal error
612
+ */
613
+ 500: ErrorResponse;
614
+ };
615
+ type GetSuggestionsError = GetSuggestionsErrors[keyof GetSuggestionsErrors];
616
+ type GetSuggestionsResponses = {
617
+ /**
618
+ * Autocomplete suggestions
619
+ */
620
+ 200: {
621
+ success: true;
622
+ requestId: string;
623
+ data: SuggestData;
624
+ cacheState: 'hit' | 'miss';
625
+ creditsUsed: number;
626
+ creditsRemaining: number;
627
+ };
628
+ };
629
+ type GetSuggestionsResponse = GetSuggestionsResponses[keyof GetSuggestionsResponses];
630
+ type GetCreditsData = {
631
+ body?: never;
632
+ path?: never;
633
+ query?: never;
634
+ url: '/v1/credits';
635
+ };
636
+ type GetCreditsErrors = {
637
+ /**
638
+ * Unauthorized
639
+ */
640
+ 401: ErrorResponse;
641
+ };
642
+ type GetCreditsError = GetCreditsErrors[keyof GetCreditsErrors];
643
+ type GetCreditsResponses = {
644
+ /**
645
+ * Credit balance
646
+ */
647
+ 200: {
648
+ success: true;
649
+ requestId: string;
650
+ data: CreditsData;
651
+ };
652
+ };
653
+ type GetCreditsResponse = GetCreditsResponses[keyof GetCreditsResponses];
654
+ type GetLogsData = {
655
+ body?: never;
656
+ path?: never;
657
+ query?: {
658
+ /**
659
+ * Time window: 'today', the last 7 days, or the last 30 days.
660
+ */
661
+ days?: 'today' | '7' | '30';
662
+ /**
663
+ * Filter logs to a single endpoint, e.g. /video.
664
+ */
665
+ endpoint?: string;
666
+ /**
667
+ * Zero-based page index. Page size is fixed at 50 entries.
668
+ */
669
+ page?: number;
670
+ };
671
+ url: '/v1/logs';
672
+ };
673
+ type GetLogsErrors = {
674
+ /**
675
+ * Unauthorized
676
+ */
677
+ 401: ErrorResponse;
678
+ };
679
+ type GetLogsError = GetLogsErrors[keyof GetLogsErrors];
680
+ type GetLogsResponses = {
681
+ /**
682
+ * Request logs
683
+ */
684
+ 200: {
685
+ success: true;
686
+ requestId: string;
687
+ data: LogsData;
688
+ };
689
+ };
690
+ type GetLogsResponse = GetLogsResponses[keyof GetLogsResponses];
691
+ type GetUsageData = {
692
+ body?: never;
693
+ path?: never;
694
+ query?: {
695
+ /**
696
+ * Time window: 'today', the last 7 days, or the last 30 days.
697
+ */
698
+ days?: 'today' | '7' | '30';
699
+ /**
700
+ * Timezone offset in minutes used to bucket activity into days. Defaults to UTC.
701
+ */
702
+ tz?: string;
703
+ };
704
+ url: '/v1/usage';
705
+ };
706
+ type GetUsageErrors = {
707
+ /**
708
+ * Unauthorized
709
+ */
710
+ 401: ErrorResponse;
711
+ };
712
+ type GetUsageError = GetUsageErrors[keyof GetUsageErrors];
713
+ type GetUsageResponses = {
714
+ /**
715
+ * Daily usage
716
+ */
717
+ 200: {
718
+ success: true;
719
+ requestId: string;
720
+ data: UsageData;
721
+ };
722
+ };
723
+ type GetUsageResponse = GetUsageResponses[keyof GetUsageResponses];
724
+ type ClientOptions = {
725
+ baseUrl: 'https://api.stophy.dev' | (string & {});
726
+ };
727
+
728
+ /** A video response with `data` narrowed to the shape for a given request `type`. */
729
+ type VideoResponseFor<D> = Omit<GetVideoResponse, "data"> & {
730
+ data: D;
731
+ };
732
+
733
+ interface StophyOptions {
734
+ /** API key from your dashboard. Sent as `Authorization: Bearer <key>`. */
735
+ apiKey: string;
736
+ /** Defaults to `https://api.stophy.dev`. */
737
+ baseUrl?: string;
738
+ /** Bring your own `fetch` (handy for tests or non-global runtimes). */
739
+ fetch?: typeof globalThis.fetch;
740
+ /** Sent with every request. */
741
+ headers?: Record<string, string>;
742
+ /**
743
+ * Retry attempts for transient failures (network errors and
744
+ * 429/500/502/503/504). Set to `0` to disable. Defaults to `2`.
745
+ */
746
+ maxRetries?: number;
747
+ /** Base delay for backoff, in ms. Defaults to `500`. */
748
+ retryInitialDelayMs?: number;
749
+ }
750
+ /** Thrown when the API responds with a non-2xx status. */
751
+ declare class StophyError extends Error {
752
+ readonly code?: ErrorResponse["code"];
753
+ readonly status: number;
754
+ readonly requestId?: string;
755
+ readonly details?: unknown;
756
+ constructor(message: string, opts: {
757
+ status: number;
758
+ code?: ErrorResponse["code"];
759
+ requestId?: string;
760
+ details?: unknown;
761
+ });
762
+ }
763
+ /**
764
+ * Stophy API client — YouTube context API for AI agents.
765
+ *
766
+ * ```ts
767
+ * const stophy = new Stophy({ apiKey: process.env.STOPHY_API_KEY! });
768
+ * const { data } = await stophy.video({ type: "transcript", videoUrl });
769
+ * ```
770
+ */
771
+ declare class Stophy {
772
+ /** The underlying fetch client, if you need lower-level access. */
773
+ readonly client: Client;
774
+ constructor(options: StophyOptions);
775
+ /** Video details, transcript, comments, replies, or live chat — pick with `type`. */
776
+ video(body: GetVideoData["body"] & {
777
+ type: "details";
778
+ }): Promise<VideoResponseFor<VideoDetailsData>>;
779
+ video(body: GetVideoData["body"] & {
780
+ type: "transcript";
781
+ }): Promise<VideoResponseFor<TranscriptResult>>;
782
+ video(body: GetVideoData["body"] & {
783
+ type: "comments" | "replies";
784
+ }): Promise<VideoResponseFor<CommentsData>>;
785
+ video(body: GetVideoData["body"] & {
786
+ type: "livechat";
787
+ }): Promise<VideoResponseFor<LiveChatData>>;
788
+ video(body: GetVideoData["body"]): Promise<GetVideoResponse>;
789
+ /** Search YouTube, optionally filtered by type, sort, date, duration, and features. */
790
+ search(body: SearchVideosData["body"]): Promise<SearchVideosResponse>;
791
+ /** Channel metadata and content. Switch sections with `tab`. */
792
+ channel(body: GetChannelData["body"]): Promise<GetChannelResponse>;
793
+ /** Playlist items. Page through long playlists with `continuationToken`. */
794
+ playlist(body: GetPlaylistData["body"]): Promise<GetPlaylistResponse>;
795
+ /** Search autocomplete suggestions. */
796
+ suggest(query: GetSuggestionsData["query"]): Promise<GetSuggestionsResponse>;
797
+ /** Your current credit balance. */
798
+ credits(): Promise<GetCreditsResponse>;
799
+ /** Recent API request logs. */
800
+ logs(query?: GetLogsData["query"]): Promise<GetLogsResponse>;
801
+ /** Daily credit and request counts. */
802
+ usage(query?: GetUsageData["query"]): Promise<GetUsageResponse>;
803
+ }
804
+
805
+ export { type ChannelData, type ChannelLink, type ChannelProfile, type ClientOptions, type Comment, type CommentsData, type ContentItem, type CreditsData, type EmptyState, type ErrorResponse, type GetChannelData, type GetChannelError, type GetChannelErrors, type GetChannelResponse, type GetChannelResponses, type GetCreditsData, type GetCreditsError, type GetCreditsErrors, type GetCreditsResponse, type GetCreditsResponses, type GetLogsData, type GetLogsError, type GetLogsErrors, type GetLogsResponse, type GetLogsResponses, type GetPlaylistData, type GetPlaylistError, type GetPlaylistErrors, type GetPlaylistResponse, type GetPlaylistResponses, type GetSuggestionsData, type GetSuggestionsError, type GetSuggestionsErrors, type GetSuggestionsResponse, type GetSuggestionsResponses, type GetUsageData, type GetUsageError, type GetUsageErrors, type GetUsageResponse, type GetUsageResponses, type GetVideoData, type GetVideoError, type GetVideoErrors, type GetVideoResponse, type GetVideoResponses, type LiveChatData, type LiveChatMessage, type LogEntry, type LogsData, type PlaylistData, type PlaylistItem, type PlaylistMeta, type RelatedVideo, type SearchChannel, type SearchData, type SearchItem, type SearchPlaylist, type SearchShort, type SearchVideo, type SearchVideosData, type SearchVideosError, type SearchVideosErrors, type SearchVideosResponse, type SearchVideosResponses, Stophy, StophyError, type StophyOptions, type SuggestData, type Thumbnail, type TranscriptLanguage, type TranscriptResult, type TranscriptSegment, type UsageData, type UsageItem, type VideoData, type VideoDetails, type VideoDetailsData, Stophy as default };