stophy 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ type ErrorResponse = {
8
8
  /**
9
9
  * Machine-readable error code.
10
10
  */
11
- code?: 'UNAUTHORIZED' | 'INSUFFICIENT_CREDITS' | 'BAD_REQUEST' | 'INVALID_INPUT' | 'NOT_FOUND' | 'CONCURRENCY_LIMITED' | 'INTERNAL_ERROR';
11
+ code?: "UNAUTHORIZED" | "INSUFFICIENT_CREDITS" | "BAD_REQUEST" | "INVALID_INPUT" | "NOT_FOUND" | "CONCURRENCY_LIMITED" | "UPSTREAM_UNAVAILABLE" | "INTERNAL_ERROR";
12
12
  /**
13
13
  * Human-readable error message.
14
14
  */
@@ -45,37 +45,37 @@ type TranscriptResult = {
45
45
  };
46
46
  type VideoDetails = {
47
47
  id: string;
48
- type?: 'video';
48
+ type: "video";
49
49
  videoUrl: string;
50
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;
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
64
  thumbnails: Array<Thumbnail>;
65
65
  };
66
66
  type RelatedVideo = {
67
67
  id: string;
68
- type?: 'video';
68
+ type: "video";
69
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;
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
79
  thumbnails: Array<Thumbnail>;
80
80
  };
81
81
  type VideoDetailsData = {
@@ -87,21 +87,29 @@ type Comment = {
87
87
  text: string | null;
88
88
  author: string | null;
89
89
  authorId: string | null;
90
- authorThumbnail?: string | null;
90
+ authorThumbnail: string | null;
91
91
  hasChannelOwnerReplied: boolean;
92
92
  isChannelOwner: boolean;
93
93
  isHearted: boolean;
94
94
  isPinned: boolean;
95
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;
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
103
  };
104
104
  type CommentsData = {
105
+ /**
106
+ * Present for top-level comment requests.
107
+ */
108
+ videoId?: string;
109
+ /**
110
+ * Resolved sort order for top-level comment requests.
111
+ */
112
+ sortBy?: "any" | "latest" | "top";
105
113
  items: Array<Comment>;
106
114
  continuationToken: string | null;
107
115
  empty?: EmptyState;
@@ -109,20 +117,20 @@ type CommentsData = {
109
117
  type LiveChatMessage = {
110
118
  id: string;
111
119
  text: string;
112
- author?: string | null;
113
- authorId?: string | null;
114
- timestampUsec?: string | null;
120
+ author: string | null;
121
+ authorId: string | null;
122
+ timestampUsec: string | null;
115
123
  isOwner: boolean;
116
124
  isModerator: boolean;
117
125
  isVerified: boolean;
118
- superChatAmount?: string | null;
119
- superChatCurrency?: string | null;
126
+ superChatAmount: string | null;
127
+ superChatCurrency: string | null;
120
128
  };
121
129
  type LiveChatData = {
122
- status: string;
130
+ status: "live" | "upcoming" | "replay" | "chat_disabled" | "not_live";
123
131
  isLive: boolean;
124
- concurrentViewers?: number | null;
125
- pollIntervalMs?: number | null;
132
+ concurrentViewers: number | null;
133
+ pollIntervalMs: number | null;
126
134
  messages: Array<LiveChatMessage>;
127
135
  continuationToken: string | null;
128
136
  };
@@ -131,75 +139,76 @@ type LiveChatData = {
131
139
  */
132
140
  type VideoData = VideoDetailsData | TranscriptResult | CommentsData | LiveChatData;
133
141
  type SearchVideo = {
134
- type: 'video';
142
+ type: "video";
135
143
  id: string;
136
144
  videoUrl: string;
137
145
  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;
146
+ author: string | null;
147
+ authorId: string | null;
148
+ description: string | null;
149
+ duration: string | null;
150
+ durationSec: number | null;
151
+ durationText: string | null;
152
+ isLive: boolean;
153
+ isUpcoming: boolean;
154
+ isVerified: boolean;
155
+ viewCount: number | null;
156
+ viewCountText: string | null;
157
+ publishedAt: string | null;
158
+ publishedAtText: string | null;
151
159
  thumbnails: Array<Thumbnail>;
152
160
  };
153
161
  type SearchShort = {
154
- type: 'short';
162
+ type: "short";
155
163
  id: string;
156
164
  shortUrl: string;
157
165
  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;
166
+ viewCount: number | null;
167
+ viewCountText: string | null;
168
168
  thumbnails: Array<Thumbnail>;
169
169
  };
170
170
  type SearchPlaylist = {
171
- type: 'playlist';
171
+ type: "playlist";
172
172
  id: string;
173
173
  playlistUrl: string;
174
174
  title: string;
175
- author?: string | null;
176
- authorId?: string | null;
177
- videoCount?: number | null;
178
- videoCountText?: string | null;
175
+ author: string | null;
176
+ authorId: string | null;
177
+ videoCount: number | null;
178
+ videoCountText: string | null;
179
179
  thumbnails: Array<Thumbnail>;
180
180
  };
181
181
  type SearchChannel = {
182
- type: 'channel';
182
+ type: "channel";
183
183
  id: string;
184
184
  channelUrl: string;
185
185
  name: string;
186
- handle?: string | null;
187
- description?: string | null;
188
- subscriberCount?: number | null;
189
- subscriberCountText?: string | null;
190
- isVerified?: boolean;
186
+ handle: string | null;
187
+ description: string | null;
188
+ subscriberCount: number | null;
189
+ subscriberCountText: string | null;
190
+ isVerified: boolean;
191
191
  thumbnails: Array<Thumbnail>;
192
192
  };
193
193
  type SearchItem = ({
194
- type?: 'video';
194
+ type?: "video";
195
195
  } & SearchVideo) | ({
196
- type?: 'short';
196
+ type?: "short";
197
197
  } & SearchShort) | ({
198
- type?: 'playlist';
198
+ type?: "playlist";
199
199
  } & SearchPlaylist) | ({
200
- type?: 'channel';
200
+ type?: "channel";
201
201
  } & SearchChannel);
202
+ type SearchQuery = {
203
+ q: string;
204
+ type?: "video" | "short" | "channel" | "playlist" | "movie";
205
+ sortBy?: "relevance" | "popularity" | "date" | "rating";
206
+ uploadDate?: "today" | "week" | "month" | "year";
207
+ duration?: "short" | "medium" | "long";
208
+ features?: Array<string>;
209
+ };
202
210
  type SearchData = {
211
+ query: SearchQuery;
203
212
  items: Array<SearchItem>;
204
213
  continuationToken: string | null;
205
214
  estimatedResults?: number;
@@ -214,11 +223,11 @@ type ChannelProfile = {
214
223
  name: string | null;
215
224
  handle: string | null;
216
225
  channelUrl: string | null;
217
- description?: string | null;
218
- subscriberCount?: number | null;
219
- subscriberCountText?: string | null;
220
- videoCount?: number | null;
221
- videoCountText?: string | null;
226
+ description: string | null;
227
+ subscriberCount: number | null;
228
+ subscriberCountText: string | null;
229
+ videoCount: number | null;
230
+ videoCountText: string | null;
222
231
  viewCount?: number | null;
223
232
  viewCountText?: string | null;
224
233
  isVerified: boolean;
@@ -228,59 +237,90 @@ type ChannelProfile = {
228
237
  banners: Array<Thumbnail>;
229
238
  links?: Array<ChannelLink> | null;
230
239
  };
231
- type ContentItem = {
240
+ type ChannelVideo = {
232
241
  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;
242
+ type: "video";
243
+ title: string | null;
244
+ videoUrl: string;
245
+ author: string | null;
246
+ authorId: string | null;
247
+ duration: string | null;
248
+ durationSec: number | null;
249
+ durationText: string | null;
250
+ isLive: boolean;
251
+ isUpcoming: boolean;
252
+ upcomingAt: string | null;
253
+ viewCount: number | null;
254
+ viewCountText: string | null;
255
+ publishedAt: string | null;
256
+ publishedAtText: string | null;
257
+ thumbnails: Array<Thumbnail>;
258
+ };
259
+ type ChannelShort = {
260
+ id: string;
261
+ type: "short";
262
+ shortUrl: string;
263
+ title: string | null;
264
+ author: string | null;
265
+ authorId: string | null;
266
+ viewCount: number | null;
267
+ viewCountText: string | null;
268
+ thumbnails: Array<Thumbnail>;
269
+ };
270
+ type ChannelPlaylist = {
271
+ id: string;
272
+ type: "playlist";
273
+ playlistUrl: string;
274
+ title: string | null;
275
+ author: string | null;
276
+ authorId: string | null;
277
+ videoCount: string | null;
246
278
  thumbnails: Array<Thumbnail>;
247
279
  };
280
+ type ContentItem = ({
281
+ type?: "video";
282
+ } & ChannelVideo) | ({
283
+ type?: "short";
284
+ } & ChannelShort) | ({
285
+ type?: "playlist";
286
+ } & ChannelPlaylist);
248
287
  type ChannelData = {
249
288
  channel: ChannelProfile | null;
250
- tab?: string | null;
289
+ tab: "video" | "short" | "playlist" | "about";
251
290
  items?: Array<ContentItem>;
252
291
  continuationToken?: string | null;
253
292
  empty?: EmptyState;
254
293
  };
255
294
  type PlaylistMeta = {
256
295
  id: string;
257
- type?: 'playlist';
296
+ type: "playlist";
258
297
  playlistUrl: string;
259
- title?: string | null;
260
- author?: string | null;
261
- authorId?: string | null;
262
- description?: string | null;
263
- videoCount?: string | null;
298
+ title: string | null;
299
+ author: string | null;
300
+ authorId: string | null;
301
+ description: string | null;
302
+ videoCount: string | null;
264
303
  thumbnails: Array<Thumbnail>;
265
304
  };
266
305
  type PlaylistItem = {
267
306
  id: string;
268
- type?: 'video';
307
+ type: "video";
269
308
  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;
309
+ title: string | null;
310
+ author: string | null;
311
+ authorId: string | null;
312
+ duration: string | null;
313
+ durationSec: number | null;
314
+ durationText: string | null;
315
+ index: number | null;
316
+ isLive: boolean;
317
+ isPlayable: boolean;
318
+ isUpcoming: boolean;
319
+ upcomingAt: string | null;
320
+ viewCount: number | null;
321
+ viewCountText: string | null;
322
+ publishedAt: string | null;
323
+ publishedAtText: string | null;
284
324
  thumbnails: Array<Thumbnail>;
285
325
  };
286
326
  type PlaylistData = {
@@ -332,27 +372,33 @@ type GetVideoData = {
332
372
  /**
333
373
  * The type of data to retrieve.
334
374
  */
335
- type: 'details' | 'transcript' | 'comments' | 'replies' | 'livechat';
375
+ type: "details" | "transcript" | "comments" | "livechat";
336
376
  /**
337
- * Full YouTube video URL. Not required when type is replies.
377
+ * Full YouTube video URL.
338
378
  */
339
379
  videoUrl: string;
340
380
  /**
341
381
  * Comment sort order. Only applies when type is comments.
342
382
  */
343
- sortBy?: 'latest' | 'top';
383
+ sortBy?: "latest" | "top";
344
384
  /**
345
385
  * 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
386
  */
347
- chatType?: 'top' | 'live';
387
+ chatType?: "top" | "live";
348
388
  /**
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.
389
+ * For comments, pass a previous comments response token. For livechat, pass the previous livechat token to poll for new messages.
350
390
  */
351
391
  continuationToken?: string;
392
+ } | {
393
+ type: "replies";
394
+ /**
395
+ * The repliesToken from a top-level comment.
396
+ */
397
+ continuationToken: string;
352
398
  };
353
399
  path?: never;
354
400
  query?: never;
355
- url: '/v1/video';
401
+ url: "/v1/video";
356
402
  };
357
403
  type GetVideoErrors = {
358
404
  /**
@@ -367,6 +413,10 @@ type GetVideoErrors = {
367
413
  * Insufficient credits
368
414
  */
369
415
  402: ErrorResponse;
416
+ /**
417
+ * Video or captions not found
418
+ */
419
+ 404: ErrorResponse;
370
420
  /**
371
421
  * Rate limited
372
422
  */
@@ -375,6 +425,10 @@ type GetVideoErrors = {
375
425
  * Internal error
376
426
  */
377
427
  500: ErrorResponse;
428
+ /**
429
+ * Upstream video data temporarily unavailable
430
+ */
431
+ 503: ErrorResponse;
378
432
  };
379
433
  type GetVideoError = GetVideoErrors[keyof GetVideoErrors];
380
434
  type GetVideoResponses = {
@@ -385,7 +439,7 @@ type GetVideoResponses = {
385
439
  success: true;
386
440
  requestId: string;
387
441
  data: VideoData;
388
- cacheState: 'hit' | 'miss';
442
+ cacheState: "hit" | "miss";
389
443
  creditsUsed: number;
390
444
  creditsRemaining: number;
391
445
  };
@@ -400,23 +454,23 @@ type SearchVideosData = {
400
454
  /**
401
455
  * Filter by content type.
402
456
  */
403
- type?: 'video' | 'short' | 'channel' | 'playlist' | 'movie';
457
+ type?: "video" | "short" | "channel" | "playlist" | "movie";
404
458
  /**
405
459
  * Sort order. Defaults to relevance.
406
460
  */
407
- sortBy?: 'relevance' | 'popularity' | 'date' | 'rating';
461
+ sortBy?: "relevance" | "popularity" | "date" | "rating";
408
462
  /**
409
463
  * Filter by upload date.
410
464
  */
411
- uploadDate?: 'today' | 'week' | 'month' | 'year';
465
+ uploadDate?: "today" | "week" | "month" | "year";
412
466
  /**
413
467
  * Duration filter. Not applicable when type is short.
414
468
  */
415
- duration?: 'short' | 'medium' | 'long';
469
+ duration?: "short" | "medium" | "long";
416
470
  /**
417
471
  * Filter by video features.
418
472
  */
419
- features?: Array<'live' | '4k' | 'hd' | 'subtitles' | 'creativeCommons' | '360' | 'vr180' | '3d' | 'hdr' | 'location' | 'purchased'>;
473
+ features?: Array<"live" | "4k" | "hd" | "subtitles" | "creativeCommons" | "360" | "vr180" | "3d" | "hdr" | "location" | "purchased">;
420
474
  /**
421
475
  * Token from a previous response to fetch the next page.
422
476
  */
@@ -424,7 +478,7 @@ type SearchVideosData = {
424
478
  };
425
479
  path?: never;
426
480
  query?: never;
427
- url: '/v1/search';
481
+ url: "/v1/search";
428
482
  };
429
483
  type SearchVideosErrors = {
430
484
  /**
@@ -457,7 +511,7 @@ type SearchVideosResponses = {
457
511
  success: true;
458
512
  requestId: string;
459
513
  data: SearchData;
460
- cacheState: 'hit' | 'miss';
514
+ cacheState: "hit" | "miss";
461
515
  creditsUsed: number;
462
516
  creditsRemaining: number;
463
517
  };
@@ -472,7 +526,7 @@ type GetChannelData = {
472
526
  /**
473
527
  * Content tab to fetch. Defaults to video.
474
528
  */
475
- tab?: 'video' | 'short' | 'playlist' | 'about';
529
+ tab?: "video" | "short" | "playlist" | "about";
476
530
  /**
477
531
  * Token from a previous response to fetch the next page.
478
532
  */
@@ -480,11 +534,11 @@ type GetChannelData = {
480
534
  /**
481
535
  * Sort order for the selected tab.
482
536
  */
483
- sortBy?: 'latest' | 'popular' | 'oldest';
537
+ sortBy?: "latest" | "popular" | "oldest";
484
538
  };
485
539
  path?: never;
486
540
  query?: never;
487
- url: '/v1/channel';
541
+ url: "/v1/channel";
488
542
  };
489
543
  type GetChannelErrors = {
490
544
  /**
@@ -517,7 +571,7 @@ type GetChannelResponses = {
517
571
  success: true;
518
572
  requestId: string;
519
573
  data: ChannelData;
520
- cacheState: 'hit' | 'miss';
574
+ cacheState: "hit" | "miss";
521
575
  creditsUsed: number;
522
576
  creditsRemaining: number;
523
577
  };
@@ -536,7 +590,7 @@ type GetPlaylistData = {
536
590
  };
537
591
  path?: never;
538
592
  query?: never;
539
- url: '/v1/playlist';
593
+ url: "/v1/playlist";
540
594
  };
541
595
  type GetPlaylistErrors = {
542
596
  /**
@@ -569,7 +623,7 @@ type GetPlaylistResponses = {
569
623
  success: true;
570
624
  requestId: string;
571
625
  data: PlaylistData;
572
- cacheState: 'hit' | 'miss';
626
+ cacheState: "hit" | "miss";
573
627
  creditsUsed: number;
574
628
  creditsRemaining: number;
575
629
  };
@@ -592,7 +646,7 @@ type GetSuggestionsData = {
592
646
  */
593
647
  gl?: string;
594
648
  };
595
- url: '/v1/suggest';
649
+ url: "/v1/suggest";
596
650
  };
597
651
  type GetSuggestionsErrors = {
598
652
  /**
@@ -621,7 +675,7 @@ type GetSuggestionsResponses = {
621
675
  success: true;
622
676
  requestId: string;
623
677
  data: SuggestData;
624
- cacheState: 'hit' | 'miss';
678
+ cacheState: "hit" | "miss";
625
679
  creditsUsed: number;
626
680
  creditsRemaining: number;
627
681
  };
@@ -631,7 +685,7 @@ type GetCreditsData = {
631
685
  body?: never;
632
686
  path?: never;
633
687
  query?: never;
634
- url: '/v1/credits';
688
+ url: "/v1/credits";
635
689
  };
636
690
  type GetCreditsErrors = {
637
691
  /**
@@ -658,7 +712,7 @@ type GetLogsData = {
658
712
  /**
659
713
  * Time window: 'today', the last 7 days, or the last 30 days.
660
714
  */
661
- days?: 'today' | '7' | '30';
715
+ days?: "today" | "7" | "30";
662
716
  /**
663
717
  * Filter logs to a single endpoint, e.g. /video.
664
718
  */
@@ -668,7 +722,7 @@ type GetLogsData = {
668
722
  */
669
723
  page?: number;
670
724
  };
671
- url: '/v1/logs';
725
+ url: "/v1/logs";
672
726
  };
673
727
  type GetLogsErrors = {
674
728
  /**
@@ -695,13 +749,13 @@ type GetUsageData = {
695
749
  /**
696
750
  * Time window: 'today', the last 7 days, or the last 30 days.
697
751
  */
698
- days?: 'today' | '7' | '30';
752
+ days?: "today" | "7" | "30";
699
753
  /**
700
754
  * Timezone offset in minutes used to bucket activity into days. Defaults to UTC.
701
755
  */
702
756
  tz?: string;
703
757
  };
704
- url: '/v1/usage';
758
+ url: "/v1/usage";
705
759
  };
706
760
  type GetUsageErrors = {
707
761
  /**
@@ -722,57 +776,45 @@ type GetUsageResponses = {
722
776
  };
723
777
  type GetUsageResponse = GetUsageResponses[keyof GetUsageResponses];
724
778
  type ClientOptions = {
725
- baseUrl: 'https://api.stophy.dev' | (string & {});
779
+ baseUrl: "https://api.stophy.dev" | (string & {});
726
780
  };
727
781
 
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;
782
+ type ChannelBody = GetChannelData["body"];
783
+ type ChannelOptions = Omit<ChannelBody, "channelUrl">;
784
+
785
+ type PlaylistBody = GetPlaylistData["body"];
786
+ type PlaylistOptions = Omit<PlaylistBody, "playlistUrl">;
787
+
788
+ type SearchBody = SearchVideosData["body"];
789
+ type SearchOptions = Omit<SearchBody, "q">;
790
+
791
+ type SuggestQuery = GetSuggestionsData["query"];
792
+ type SuggestOptions = Omit<SuggestQuery, "q">;
793
+
794
+ type VideoResponseFor<T> = Omit<GetVideoResponse, "data"> & {
795
+ data: T;
731
796
  };
797
+ type VideoUrlBody = Extract<GetVideoData["body"], {
798
+ videoUrl: string;
799
+ }>;
800
+ type CommentsOptions = Pick<VideoUrlBody, "sortBy" | "continuationToken">;
801
+ type LiveChatOptions = Pick<VideoUrlBody, "chatType" | "continuationToken">;
732
802
 
733
803
  interface StophyOptions {
734
- /** API key from your dashboard. Sent as `Authorization: Bearer <key>`. */
735
- apiKey: string;
736
- /** Defaults to `https://api.stophy.dev`. */
804
+ /** Defaults to `STOPHY_API_KEY`. */
805
+ apiKey?: string;
806
+ /** Defaults to `STOPHY_BASE_URL` or `https://api.stophy.dev`. */
737
807
  baseUrl?: string;
738
- /** Bring your own `fetch` (handy for tests or non-global runtimes). */
739
808
  fetch?: typeof globalThis.fetch;
740
- /** Sent with every request. */
741
809
  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
810
  maxRetries?: number;
747
- /** Base delay for backoff, in ms. Defaults to `500`. */
748
811
  retryInitialDelayMs?: number;
749
812
  }
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
- */
813
+ type StophyClientInput = StophyOptions | string;
814
+ /** Typed client for the Stophy API. */
771
815
  declare class Stophy {
772
- /** The underlying fetch client, if you need lower-level access. */
773
816
  readonly client: Client;
774
- constructor(options: StophyOptions);
775
- /** Video details, transcript, comments, replies, or live chat — pick with `type`. */
817
+ constructor(input?: StophyClientInput);
776
818
  video(body: GetVideoData["body"] & {
777
819
  type: "details";
778
820
  }): Promise<VideoResponseFor<VideoDetailsData>>;
@@ -786,20 +828,36 @@ declare class Stophy {
786
828
  type: "livechat";
787
829
  }): Promise<VideoResponseFor<LiveChatData>>;
788
830
  video(body: GetVideoData["body"]): Promise<GetVideoResponse>;
789
- /** Search YouTube, optionally filtered by type, sort, date, duration, and features. */
831
+ videoDetails(videoUrl: string): Promise<VideoResponseFor<VideoDetailsData>>;
832
+ transcript(videoUrl: string): Promise<VideoResponseFor<TranscriptResult>>;
833
+ comments(videoUrl: string, options?: CommentsOptions): Promise<VideoResponseFor<CommentsData>>;
834
+ replies(continuationToken: string): Promise<VideoResponseFor<CommentsData>>;
835
+ liveChat(videoUrl: string, options?: LiveChatOptions): Promise<VideoResponseFor<LiveChatData>>;
790
836
  search(body: SearchVideosData["body"]): Promise<SearchVideosResponse>;
791
- /** Channel metadata and content. Switch sections with `tab`. */
837
+ search(query: string, options?: SearchOptions): Promise<SearchVideosResponse>;
792
838
  channel(body: GetChannelData["body"]): Promise<GetChannelResponse>;
793
- /** Playlist items. Page through long playlists with `continuationToken`. */
839
+ channel(channelUrl: string, options?: ChannelOptions): Promise<GetChannelResponse>;
794
840
  playlist(body: GetPlaylistData["body"]): Promise<GetPlaylistResponse>;
795
- /** Search autocomplete suggestions. */
841
+ playlist(playlistUrl: string, options?: PlaylistOptions): Promise<GetPlaylistResponse>;
796
842
  suggest(query: GetSuggestionsData["query"]): Promise<GetSuggestionsResponse>;
797
- /** Your current credit balance. */
843
+ suggest(query: string, options?: SuggestOptions): Promise<GetSuggestionsResponse>;
798
844
  credits(): Promise<GetCreditsResponse>;
799
- /** Recent API request logs. */
800
845
  logs(query?: GetLogsData["query"]): Promise<GetLogsResponse>;
801
- /** Daily credit and request counts. */
802
846
  usage(query?: GetUsageData["query"]): Promise<GetUsageResponse>;
803
847
  }
804
848
 
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 };
849
+ /** Thrown when the Stophy API responds with a non-success status. */
850
+ declare class StophyError extends Error {
851
+ readonly code?: ErrorResponse["code"];
852
+ readonly status: number;
853
+ readonly requestId?: string;
854
+ readonly details?: unknown;
855
+ constructor(message: string, options: {
856
+ status: number;
857
+ code?: ErrorResponse["code"];
858
+ requestId?: string;
859
+ details?: unknown;
860
+ });
861
+ }
862
+
863
+ export { type ChannelData, type ChannelLink, type ChannelOptions, type ChannelPlaylist, type ChannelProfile, type ChannelShort, type ChannelVideo, type ClientOptions, type Comment, type CommentsData, type CommentsOptions, 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 LiveChatOptions, type LogEntry, type LogsData, type PlaylistData, type PlaylistItem, type PlaylistMeta, type PlaylistOptions, type RelatedVideo, type SearchChannel, type SearchData, type SearchItem, type SearchOptions, type SearchPlaylist, type SearchQuery, type SearchShort, type SearchVideo, type SearchVideosData, type SearchVideosError, type SearchVideosErrors, type SearchVideosResponse, type SearchVideosResponses, Stophy, type StophyClientInput, StophyError, type StophyOptions, type SuggestData, type SuggestOptions, type Thumbnail, type TranscriptLanguage, type TranscriptResult, type TranscriptSegment, type UsageData, type UsageItem, type VideoData, type VideoDetails, type VideoDetailsData, Stophy as default };