@captapi/sdk 0.2.0 → 0.3.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 +73 -73
- package/dist/core.js +26 -14
- package/dist/generated.d.ts +400 -362
- package/dist/generated.js +85 -65
- package/package.json +51 -51
package/README.md
CHANGED
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
# @captapi/sdk
|
|
2
|
-
|
|
3
|
-
Official typed TypeScript SDK for the [Captapi](https://captapi.com) social media API — 178 endpoints across 32 platforms (YouTube, TikTok, Instagram, Facebook, X/Twitter, Reddit, Threads, Bluesky, Pinterest, LinkedIn, Twitch, Spotify, SoundCloud, GitHub, and more).
|
|
4
|
-
|
|
5
|
-
- Zero dependencies — built on native `fetch` (Node 18+, Deno, Bun, edge runtimes)
|
|
6
|
-
- Full type definitions for every endpoint and parameter — great autocomplete for humans and AI coding agents
|
|
7
|
-
- Errors always throw a `CaptapiError` with status, code, and detail — no silent failures
|
|
8
|
-
- One bounded retry on 502/503 (skipped when the API says the failure is persistent or already cached)
|
|
9
|
-
|
|
10
|
-
## Install
|
|
11
|
-
|
|
12
|
-
```bash
|
|
13
|
-
npm install @captapi/sdk
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Quick start
|
|
17
|
-
|
|
18
|
-
```ts
|
|
19
|
-
import { Captapi } from "@captapi/sdk";
|
|
20
|
-
|
|
21
|
-
const client = new Captapi({ apiKey: "YOUR_KEY" }); // or set CAPTAPI_API_KEY
|
|
22
|
-
|
|
23
|
-
const transcript = await client.youtube.transcript({
|
|
24
|
-
url: "https://youtube.com/watch?v=dQw4w9WgXcQ",
|
|
25
|
-
});
|
|
26
|
-
console.log(transcript.data);
|
|
27
|
-
|
|
28
|
-
const profile = await client.tiktok.channelDetails({ url: "https://tiktok.com/@nba" });
|
|
29
|
-
const posts = await client.reddit.subredditPosts({ url: "https://reddit.com/r/programming", limit: 25 });
|
|
30
|
-
const ads = await client.googleAdLibrary.companyAds({ advertiser: "nike.com" });
|
|
31
|
-
```
|
|
32
|
-
|
|
33
|
-
## Error handling
|
|
34
|
-
|
|
35
|
-
Every failed request throws — nothing fails silently:
|
|
36
|
-
|
|
37
|
-
```ts
|
|
38
|
-
import { Captapi, CaptapiError } from "@captapi/sdk";
|
|
39
|
-
|
|
40
|
-
try {
|
|
41
|
-
await client.instagram.channelDetails({ url: "https://instagram.com/whoever" });
|
|
42
|
-
} catch (err) {
|
|
43
|
-
if (err instanceof CaptapiError) {
|
|
44
|
-
console.error(err.status, err.code, err.detail);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
## Options
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
new Captapi({
|
|
53
|
-
apiKey: "...", // default: process.env.CAPTAPI_API_KEY
|
|
54
|
-
baseUrl: "https://api.captapi.com", // default
|
|
55
|
-
timeoutMs: 120_000, // default
|
|
56
|
-
});
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
## Responses
|
|
60
|
-
|
|
61
|
-
All methods resolve to the standard Captapi envelope:
|
|
62
|
-
|
|
63
|
-
```json
|
|
64
|
-
{ "success": true, "data": { ... } }
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
## Links
|
|
68
|
-
|
|
69
|
-
- [Documentation](https://captapi.com/docs)
|
|
70
|
-
- [Get an API key (100 free credits)](https://captapi.com/dashboard/api-keys)
|
|
71
|
-
- Python SDK: [`pip install captapi`](https://pypi.org/project/captapi/)
|
|
72
|
-
- MCP server for AI agents: [`@captapi/mcp`](https://www.npmjs.com/package/@captapi/mcp)
|
|
73
|
-
- CLI: [`@captapi/cli`](https://www.npmjs.com/package/@captapi/cli)
|
|
1
|
+
# @captapi/sdk
|
|
2
|
+
|
|
3
|
+
Official typed TypeScript SDK for the [Captapi](https://captapi.com) social media API — 178 endpoints across 32 platforms (YouTube, TikTok, Instagram, Facebook, X/Twitter, Reddit, Threads, Bluesky, Pinterest, LinkedIn, Twitch, Spotify, SoundCloud, GitHub, and more).
|
|
4
|
+
|
|
5
|
+
- Zero dependencies — built on native `fetch` (Node 18+, Deno, Bun, edge runtimes)
|
|
6
|
+
- Full type definitions for every endpoint and parameter — great autocomplete for humans and AI coding agents
|
|
7
|
+
- Errors always throw a `CaptapiError` with status, code, and detail — no silent failures
|
|
8
|
+
- One bounded retry on 502/503 (skipped when the API says the failure is persistent or already cached)
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
npm install @captapi/sdk
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
## Quick start
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
import { Captapi } from "@captapi/sdk";
|
|
20
|
+
|
|
21
|
+
const client = new Captapi({ apiKey: "YOUR_KEY" }); // or set CAPTAPI_API_KEY
|
|
22
|
+
|
|
23
|
+
const transcript = await client.youtube.transcript({
|
|
24
|
+
url: "https://youtube.com/watch?v=dQw4w9WgXcQ",
|
|
25
|
+
});
|
|
26
|
+
console.log(transcript.data);
|
|
27
|
+
|
|
28
|
+
const profile = await client.tiktok.channelDetails({ url: "https://tiktok.com/@nba" });
|
|
29
|
+
const posts = await client.reddit.subredditPosts({ url: "https://reddit.com/r/programming", limit: 25 });
|
|
30
|
+
const ads = await client.googleAdLibrary.companyAds({ advertiser: "nike.com" });
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Error handling
|
|
34
|
+
|
|
35
|
+
Every failed request throws — nothing fails silently:
|
|
36
|
+
|
|
37
|
+
```ts
|
|
38
|
+
import { Captapi, CaptapiError } from "@captapi/sdk";
|
|
39
|
+
|
|
40
|
+
try {
|
|
41
|
+
await client.instagram.channelDetails({ url: "https://instagram.com/whoever" });
|
|
42
|
+
} catch (err) {
|
|
43
|
+
if (err instanceof CaptapiError) {
|
|
44
|
+
console.error(err.status, err.code, err.detail);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Options
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
new Captapi({
|
|
53
|
+
apiKey: "...", // default: process.env.CAPTAPI_API_KEY
|
|
54
|
+
baseUrl: "https://api.captapi.com", // default
|
|
55
|
+
timeoutMs: 120_000, // default
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## Responses
|
|
60
|
+
|
|
61
|
+
All methods resolve to the standard Captapi envelope:
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{ "success": true, "data": { ... } }
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
## Links
|
|
68
|
+
|
|
69
|
+
- [Documentation](https://captapi.com/docs)
|
|
70
|
+
- [Get an API key (100 free credits)](https://captapi.com/dashboard/api-keys)
|
|
71
|
+
- Python SDK: [`pip install captapi`](https://pypi.org/project/captapi/)
|
|
72
|
+
- MCP server for AI agents: [`@captapi/mcp`](https://www.npmjs.com/package/@captapi/mcp)
|
|
73
|
+
- CLI: [`@captapi/cli`](https://www.npmjs.com/package/@captapi/cli)
|
package/dist/core.js
CHANGED
|
@@ -15,18 +15,24 @@ export class CaptapiError extends Error {
|
|
|
15
15
|
}
|
|
16
16
|
const RETRY_STATUSES = new Set([502, 503]);
|
|
17
17
|
const RETRY_DELAY_MS = 500;
|
|
18
|
+
function errorBag(body) {
|
|
19
|
+
if (!body || typeof body !== "object")
|
|
20
|
+
return null;
|
|
21
|
+
const root = body;
|
|
22
|
+
if (root.error && typeof root.error === "object") {
|
|
23
|
+
return root.error;
|
|
24
|
+
}
|
|
25
|
+
if (root.detail && typeof root.detail === "object") {
|
|
26
|
+
return root.detail;
|
|
27
|
+
}
|
|
28
|
+
return root;
|
|
29
|
+
}
|
|
18
30
|
function shouldRetry(status, body) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
? body.detail
|
|
23
|
-
: body;
|
|
24
|
-
if (bag && typeof bag === "object") {
|
|
25
|
-
const flags = bag;
|
|
26
|
-
if (flags.persistent === true || flags.replayed === true)
|
|
27
|
-
return false;
|
|
31
|
+
const bag = errorBag(body);
|
|
32
|
+
if (bag && typeof bag.retryable === "boolean") {
|
|
33
|
+
return bag.retryable === true;
|
|
28
34
|
}
|
|
29
|
-
return
|
|
35
|
+
return RETRY_STATUSES.has(status);
|
|
30
36
|
}
|
|
31
37
|
export class HttpCore {
|
|
32
38
|
apiKey;
|
|
@@ -45,13 +51,19 @@ export class HttpCore {
|
|
|
45
51
|
this.fetchImpl = options.fetch ?? globalThis.fetch;
|
|
46
52
|
}
|
|
47
53
|
fail(path, status, body) {
|
|
48
|
-
const
|
|
49
|
-
const
|
|
50
|
-
|
|
54
|
+
const bag = errorBag(body);
|
|
55
|
+
const detail = bag ?? body?.detail ?? body?.error ?? body;
|
|
56
|
+
const code = typeof bag?.code === "string"
|
|
57
|
+
? bag.code
|
|
51
58
|
: typeof body?.error === "string"
|
|
52
59
|
? body.error
|
|
53
60
|
: undefined;
|
|
54
|
-
|
|
61
|
+
const message = typeof bag?.message === "string"
|
|
62
|
+
? bag.message
|
|
63
|
+
: typeof detail === "string"
|
|
64
|
+
? detail
|
|
65
|
+
: JSON.stringify(detail ?? "unknown error");
|
|
66
|
+
return new CaptapiError(`Captapi ${path} returned ${status}: ${message}`, status, code, detail);
|
|
55
67
|
}
|
|
56
68
|
async parseBody(res) {
|
|
57
69
|
try {
|