stophy 0.3.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,7 +1,6 @@
1
- # stophy
2
-
3
- Official TypeScript SDK for [Stophy](https://stophy.dev) **YouTube context API for AI agents**. Search videos, fetch transcripts, read comments and live chat, inspect channels and playlists, use YouTube Music and YouTube Kids, and get autocomplete suggestions, all returned as structured JSON.
1
+ # Stophy for TypeScript
4
2
 
3
+ Get public web data in your TypeScript or JavaScript code: search results, videos, social posts, places, products, jobs, homes, and more. Every method and result is typed.
5
4
 
6
5
  ## Install
7
6
 
@@ -9,112 +8,89 @@ Official TypeScript SDK for [Stophy](https://stophy.dev) **YouTube context API
9
8
  npm install stophy
10
9
  ```
11
10
 
12
- Get an API key from your [Stophy dashboard](https://stophy.dev). The SDK sends it as `Authorization: Bearer <key>` on every request.
13
-
14
- ## Quick start
11
+ ## Try it without a key
15
12
 
16
13
  ```ts
17
14
  import { Stophy } from "stophy";
18
15
 
19
- const stophy = new Stophy(); // reads STOPHY_API_KEY
20
- const result = await stophy.transcript(
21
- "https://www.youtube.com/watch?v=D7liwdjvhWc",
22
- );
23
- console.log(result.data.text);
16
+ const result = await new Stophy().web.search({ query: "bun runtime" });
17
+ console.log(result.data.results);
24
18
  ```
25
19
 
26
- ## Methods
27
-
28
- | Method | Description |
29
- | --- | --- |
30
- | `stophy.videoDetails(url)` | Video metadata and related videos |
31
- | `stophy.transcript(url)` | Timestamped captions and full text |
32
- | `stophy.comments(url, options?)` | Top-level comments |
33
- | `stophy.replies(token)` | Replies for a comment thread |
34
- | `stophy.liveChat(url, options?)` | Live stream chat messages |
35
- | `stophy.search(query, options?)` | Search with filters |
36
- | `stophy.channel(url, options?)` | Channel metadata and content |
37
- | `stophy.playlist(url, options?)` | Playlist items, paginated |
38
- | `stophy.suggest(query, options?)` | Search autocomplete suggestions |
39
- | `stophy.music(body)` | YouTube Music search, suggestions, songs, lyrics, albums, artists, playlists |
40
- | `stophy.kids(body)` | YouTube Kids search and video metadata |
41
- | `stophy.credits()` | Current credit balance |
42
- | `stophy.logs(query?)` | Recent request logs |
43
- | `stophy.usage(query?)` | Daily credit/request counts |
44
-
45
- ### Examples
20
+ Web search, YouTube search, and YouTube transcripts work without a key, with a small free allowance. Every other method throws a `StophyError` with the code `unauthorized`.
21
+
22
+ ## Use an API key
23
+
24
+ Get a key from the [dashboard](https://stophy.dev/dashboard). Keys start with `st_`. Set it as `STOPHY_API_KEY`, or pass it in:
46
25
 
47
26
  ```ts
48
- // Search
49
- const results = await stophy.search("typescript tutorial", {
50
- sortBy: "popularity",
51
- duration: "long",
52
- });
53
-
54
- // Comments (top-level), then replies to a comment.
55
- // `video()` is overloaded on `type`, so `data` is typed - no casts needed.
56
- const comments = await stophy.comments(videoUrl, { sortBy: "top" });
57
- const firstReplyToken = comments.data.items[0]?.repliesToken;
58
- if (firstReplyToken) {
59
- const replies = await stophy.replies(firstReplyToken);
60
- }
27
+ const stophy = new Stophy({ apiKey: "st_..." });
61
28
 
62
- // Channel videos
63
- const channel = await stophy.channel("https://www.youtube.com/@mkbhd", {
64
- tab: "video",
65
- });
66
-
67
- // Autocomplete
68
- const { data: s } = await stophy.suggest("react", { hl: "en", gl: "US" });
69
- console.log(s.suggestions);
70
-
71
- // YouTube Music
72
- const music = await stophy.music({
73
- type: "search",
74
- q: "lofi",
75
- searchType: "song",
76
- });
77
- console.log(music.data.items);
78
-
79
- // YouTube Kids
80
- const kids = await stophy.kids({ type: "search", q: "science" });
81
- console.log(kids.data.items);
82
-
83
- // Account
84
- console.log((await stophy.credits()).data.credits);
29
+ const videos = await stophy.youtube.search({ query: "bun runtime", limit: 5 });
30
+ console.log(videos.data.results);
85
31
  ```
86
32
 
87
- ### Pagination
33
+ `new Stophy("st_...")` works too.
88
34
 
89
- List endpoints return a `continuationToken`. Pass it back in to fetch the next page:
35
+ Methods follow the source and the command: `stophy.maps.search(...)`, `stophy.reddit.subreddit(...)`, `stophy.youtube.comments.replies(...)`. Each result has `data`, `creditsUsed`, and `requestId`.
36
+
37
+ ## Get markdown for a model
90
38
 
91
39
  ```ts
92
- let token: string | undefined;
93
- do {
94
- const page = await stophy.search("lofi", { continuationToken: token });
95
- // ...handle page.data.items
96
- token = page.data.continuationToken ?? undefined;
97
- } while (token);
40
+ const markdown = await stophy.youtube.search(
41
+ { query: "bun runtime", limit: 5 },
42
+ { format: "markdown" },
43
+ );
98
44
  ```
99
45
 
100
- ## Errors
46
+ With `format: "markdown"`, the method returns a string.
47
+
48
+ ## Get the next page
49
+
50
+ When there are more results, `data.cursor` is set. Pass it back to get the next page:
51
+
52
+ ```ts
53
+ const first = await stophy.reddit.search({ query: "bun" });
54
+ const next = await stophy.reddit.search({ query: "bun", cursor: first.data.cursor });
55
+ ```
101
56
 
102
- Non-2xx responses throw a `StophyError`:
57
+ ## Handle errors
103
58
 
104
59
  ```ts
105
- import { Stophy, StophyError } from "stophy";
60
+ import { StophyError } from "stophy";
106
61
 
107
62
  try {
108
- await stophy.credits();
109
- } catch (err) {
110
- if (err instanceof StophyError) {
111
- console.error(err.status, err.code, err.message, err.requestId);
112
- // err.code: "UNAUTHORIZED" | "INSUFFICIENT_CREDITS" | "BAD_REQUEST" |
113
- // "INVALID_INPUT" | "NOT_FOUND" | "CONCURRENCY_LIMITED" | "INTERNAL_ERROR"
63
+ await stophy.reddit.search({ query: "bun" });
64
+ } catch (error) {
65
+ if (error instanceof StophyError) {
66
+ console.log(error.code, error.retryable, error.retryAfterSeconds);
114
67
  }
115
68
  }
116
69
  ```
117
70
 
71
+ `StophyError` has `code`, `message`, `retryable`, `retryAfterSeconds`, `status`, and `requestId`.
72
+
73
+ The SDK retries network errors and the HTTP statuses 429, 500, 502, 503, and 504, and it waits as long as the API asks. If the API asks for a wait longer than 60 seconds, the SDK throws right away with `retryAfterSeconds` set.
74
+
75
+ ## Options
76
+
77
+ | Option | Default | What it does |
78
+ | --- | --- | --- |
79
+ | `apiKey` | `STOPHY_API_KEY` | Your API key |
80
+ | `baseUrl` | `STOPHY_BASE_URL`, or the Stophy API | The server to call |
81
+ | `maxRetries` | `2` | Retries per request. `0` turns retries off. |
82
+ | `timeoutMs` | `30000` | Time limit for each attempt. A timed-out attempt is not retried. |
83
+
84
+ Each method also takes `signal` to cancel the request.
85
+
86
+ ## Check your account
87
+
88
+ ```ts
89
+ const usage = await stophy.usage();
90
+ const logs = await stophy.logs({ days: 7, page: 0 });
91
+ ```
92
+
93
+ `usage` returns your balance and your all-time usage. `logs` returns your recent requests. Both need an API key.
118
94
 
119
95
  ## License
120
96