|
| 1 | +--- |
| 2 | +title: "SDKs" |
| 3 | +description: "Official typed TypeScript and Python SDKs for AnyAPI - one key, USD pricing, and a typed method for every API in the catalog." |
| 4 | +--- |
| 5 | + |
| 6 | +AnyAPI ships two official, typed SDKs so you can call any API in the catalog from |
| 7 | +your own code without hand-writing HTTP requests. Both are generated from the platform's |
| 8 | +own OpenAPI spec (222 APIs), so they track the catalog automatically. |
| 9 | + |
| 10 | +| | | |
| 11 | +|---|---| |
| 12 | +| **TypeScript / Node** | [`@getanyapi/sdk`](https://www.npmjs.com/package/@getanyapi/sdk) - zero runtime dependencies, ESM + CJS, Node 18+ and edge runtimes | |
| 13 | +| **Python** | [`getanyapi`](https://pypi.org/project/getanyapi/) - httpx + pydantic v2, Python 3.10+, sync and async clients | |
| 14 | +| **Source** | [`getanyapi-com/sdks`](https://github.com/getanyapi-com/sdks) | |
| 15 | + |
| 16 | +Every API is a typed method under its platform namespace (`client.google.search(...)`, |
| 17 | +`client.amazon.reviews(...)`), and there is a generic escape hatch to call any API by slug. |
| 18 | + |
| 19 | +## Install |
| 20 | + |
| 21 | +<CodeGroup> |
| 22 | +```bash npm |
| 23 | +npm install @getanyapi/sdk |
| 24 | +``` |
| 25 | + |
| 26 | +```bash pip |
| 27 | +pip install getanyapi |
| 28 | +``` |
| 29 | +</CodeGroup> |
| 30 | + |
| 31 | +## Authenticate |
| 32 | + |
| 33 | +Construct a client with your AnyAPI key. When you omit it, both SDKs read |
| 34 | +`ANYAPI_API_KEY` from the environment, so you never have to hardcode a secret. |
| 35 | + |
| 36 | +Need a key? Grab one from the [dashboard](https://getanyapi.com/dashboard) or mint one |
| 37 | +from the terminal - see the [Quickstart](/quickstart). |
| 38 | + |
| 39 | +<CodeGroup> |
| 40 | +```ts TypeScript |
| 41 | +import { AnyAPI } from "@getanyapi/sdk"; |
| 42 | + |
| 43 | +// Reads ANYAPI_API_KEY from the environment when apiKey is omitted. |
| 44 | +const client = new AnyAPI({ apiKey: process.env.ANYAPI_API_KEY }); |
| 45 | +``` |
| 46 | + |
| 47 | +```python Python |
| 48 | +from getanyapi import AnyAPI |
| 49 | + |
| 50 | +client = AnyAPI() # reads ANYAPI_API_KEY from the environment |
| 51 | +``` |
| 52 | +</CodeGroup> |
| 53 | + |
| 54 | +## Your first call |
| 55 | + |
| 56 | +Call any API as a typed method under its platform namespace. `res.output` is the |
| 57 | +normalized result, and the cost of the call in real US dollars is on `res.costUsd` |
| 58 | +(TypeScript) / `res.cost_usd` (Python). |
| 59 | + |
| 60 | +<CodeGroup> |
| 61 | +```ts TypeScript |
| 62 | +const res = await client.reddit.search({ query: "mechanical keyboard" }); |
| 63 | +for (const post of res.output.posts) { |
| 64 | + console.log(post.title, post.score); |
| 65 | +} |
| 66 | +console.log("charged", res.costUsd, "USD"); |
| 67 | +``` |
| 68 | + |
| 69 | +```python Python |
| 70 | +res = client.reddit.search(query="mechanical keyboard") |
| 71 | +for post in res.output.posts: |
| 72 | + print(post.title, post.score) |
| 73 | +print("charged", res.cost_usd, "USD") |
| 74 | +``` |
| 75 | +</CodeGroup> |
| 76 | + |
| 77 | +<Note> |
| 78 | + In Python, input keyword arguments mirror the wire API verbatim (camelCase where the |
| 79 | + API uses it). Output models are Pythonic: attributes are snake_case with a wire alias |
| 80 | + (`item.reviews_count` reads the wire `reviewsCount`), and `model_dump(by_alias=True)` |
| 81 | + reproduces the wire shape. |
| 82 | +</Note> |
| 83 | + |
| 84 | +## Call any API by slug |
| 85 | + |
| 86 | +Every typed method has a generic counterpart. Pass the API's slug and input to |
| 87 | +`run` to call any API in the catalog with full typing. |
| 88 | + |
| 89 | +<CodeGroup> |
| 90 | +```ts TypeScript |
| 91 | +const rev = await client.run("amazon.reviews", { product: "B07FZ8S74R", limit: 3 }); |
| 92 | +``` |
| 93 | + |
| 94 | +```python Python |
| 95 | +rev = client.run("amazon.reviews", {"product": "B07FZ8S74R", "limit": 3}) |
| 96 | +``` |
| 97 | +</CodeGroup> |
| 98 | + |
| 99 | +## Async (Python) |
| 100 | + |
| 101 | +The TypeScript SDK is promise-based, so every method is already `await`-able. In Python, |
| 102 | +use `AsyncAnyAPI` for an async client backed by the same typed surface. |
| 103 | + |
| 104 | +```python |
| 105 | +from getanyapi import AsyncAnyAPI |
| 106 | + |
| 107 | +async with AsyncAnyAPI() as client: |
| 108 | + res = await client.google.search(query="best coffee maker") |
| 109 | +``` |
| 110 | + |
| 111 | +## Not found vs error |
| 112 | + |
| 113 | +A successful call always resolves. For most APIs the payload is wrapped in a `found` |
| 114 | +flag: `output.found` is `false` when the upstream had no matching entity, which is a |
| 115 | +successful answer, not an error. Use `unwrap` to get the data or raise |
| 116 | +`ResultNotFoundError` when the result is empty. |
| 117 | + |
| 118 | +<CodeGroup> |
| 119 | +```ts TypeScript |
| 120 | +import { unwrap, ResultNotFoundError } from "@getanyapi/sdk"; |
| 121 | + |
| 122 | +const res = await client.amazon.reviews({ product: "B07FZ8S74R" }); |
| 123 | +try { |
| 124 | + const data = unwrap(res); // the typed data payload, or throws |
| 125 | +} catch (e) { |
| 126 | + if (e instanceof ResultNotFoundError) { |
| 127 | + // empty result (found: false), not an HTTP failure |
| 128 | + } |
| 129 | +} |
| 130 | +``` |
| 131 | + |
| 132 | +```python Python |
| 133 | +from getanyapi import unwrap, ResultNotFoundError |
| 134 | + |
| 135 | +res = client.amazon.reviews(product="B07FZ8S74R") |
| 136 | +try: |
| 137 | + data = unwrap(res) # the typed data payload, or raises |
| 138 | +except ResultNotFoundError: |
| 139 | + ... # empty result (found: False), not an HTTP failure |
| 140 | +``` |
| 141 | +</CodeGroup> |
| 142 | + |
| 143 | +`ResultNotFoundError` subclasses `NotFoundError`, so catching `NotFoundError` catches |
| 144 | +both an HTTP 404 and an empty result; catch `ResultNotFoundError` to handle only empty |
| 145 | +results. A few APIs (such as `reddit.search`) return their data object directly as |
| 146 | +`output` with no `found` wrapper, and `unwrap` returns it as-is without throwing. |
| 147 | + |
| 148 | +## Pagination |
| 149 | + |
| 150 | +Paginated APIs expose an iterator that yields items across pages and follows the cursor |
| 151 | +for you. Call `.pages()` on it to walk whole result pages instead, and read each page's |
| 152 | +`costUsd` / `cost_usd`. |
| 153 | + |
| 154 | +<CodeGroup> |
| 155 | +```ts TypeScript |
| 156 | +// Flatten items across pages, capped at 100 total. |
| 157 | +for await (const post of client.reddit.iterSearch({ query: "coffee" }, { maxItems: 100 })) { |
| 158 | + console.log(post.title); |
| 159 | +} |
| 160 | + |
| 161 | +// Or walk pages to read per-page cost. |
| 162 | +for await (const page of client.reddit.iterSearch({ query: "coffee" }).pages()) { |
| 163 | + console.log(page.costUsd); |
| 164 | +} |
| 165 | +``` |
| 166 | + |
| 167 | +```python Python |
| 168 | +# Flatten validated item models across pages, capped at 100 total. |
| 169 | +for post in client.reddit.iter_search(query="coffee", options={"max_items": 100}): |
| 170 | + print(post.title) |
| 171 | + |
| 172 | +# Or walk pages to read per-page cost. |
| 173 | +for page in client.reddit.iter_search(query="coffee").pages(): |
| 174 | + print(page.cost_usd) |
| 175 | +``` |
| 176 | +</CodeGroup> |
| 177 | + |
| 178 | +## Trim the response |
| 179 | + |
| 180 | +Shape the response to save context and bandwidth. `fields`, `maxItems` / |
| 181 | +`max_items`, and `summary` trim what comes back, but they do NOT change the price. |
| 182 | + |
| 183 | +<CodeGroup> |
| 184 | +```ts TypeScript |
| 185 | +await client.google.search( |
| 186 | + { query: "coffee" }, |
| 187 | + { |
| 188 | + fields: ["title", "link"], // keep only these keys on each item |
| 189 | + maxItems: 5, // cap result rows returned |
| 190 | + summary: true, // structural outline instead of full data |
| 191 | + }, |
| 192 | +); |
| 193 | +``` |
| 194 | + |
| 195 | +```python Python |
| 196 | +res = client.google.search( |
| 197 | + query="coffee", |
| 198 | + options={"fields": ["title", "link"], "max_items": 5, "summary": True}, |
| 199 | +) |
| 200 | +``` |
| 201 | +</CodeGroup> |
| 202 | + |
| 203 | +Per-call transport overrides live alongside these: `timeoutMs` and `maxRetries` (plus an |
| 204 | +`AbortSignal` via `signal`) in TypeScript, and `timeout` / `max_retries` inside `options` |
| 205 | +in Python. |
| 206 | + |
| 207 | +## Errors and retries |
| 208 | + |
| 209 | +Every failure raises an `AnyAPIError` subclass mapped from the HTTP status. Only 429 and |
| 210 | +network failures retry, with jittered exponential backoff that honors `Retry-After`; |
| 211 | +timeouts are never retried. The default `maxRetries` / `max_retries` is 2 (up to 3 |
| 212 | +attempts), and you can set it on the client or per request. |
| 213 | + |
| 214 | +| Class | HTTP | Meaning | |
| 215 | +| --- | --- | --- | |
| 216 | +| `BadRequestError` | 400 | Input failed validation | |
| 217 | +| `AuthenticationError` | 401 | Missing or invalid API key | |
| 218 | +| `InsufficientBalanceError` | 402 | Wallet balance or per-key cap exceeded | |
| 219 | +| `NotFoundError` | 404 | Slug or resource does not exist | |
| 220 | +| `ResultNotFoundError` | - | `unwrap` on an empty found-data result | |
| 221 | +| `RateLimitedError` | 429 | Too many requests (retried automatically) | |
| 222 | +| `UpstreamError` | 502 | An upstream request failed | |
| 223 | +| `ConnectionError` | 0 | Network or transport failure (retried) | |
| 224 | +| `TimeoutError` | 0 | Request exceeded its timeout (not retried) | |
| 225 | + |
| 226 | +Configure the client with `new AnyAPI({ timeoutMs, maxRetries })` in TypeScript or |
| 227 | +`AnyAPI(max_retries=...)` in Python. Every error carries a `status` and request id |
| 228 | +(`requestId` / `request_id`). |
| 229 | + |
| 230 | +## Agent signup |
| 231 | + |
| 232 | +Bootstrap a capped starter key with no account, for autonomous agents. A human funds it |
| 233 | +later by claiming it at the returned URL. See |
| 234 | +[Let your agent onboard itself](/agent-self-signup) for the full flow. |
| 235 | + |
| 236 | +<CodeGroup> |
| 237 | +```ts TypeScript |
| 238 | +import { agentSignup, AnyAPI } from "@getanyapi/sdk"; |
| 239 | + |
| 240 | +const { secret, capUsd, claimUrl } = await agentSignup({ label: "my-agent" }); |
| 241 | +const client = new AnyAPI({ apiKey: secret }); |
| 242 | +``` |
| 243 | + |
| 244 | +```python Python |
| 245 | +from getanyapi import agent_signup, AnyAPI |
| 246 | + |
| 247 | +result = agent_signup(label="my-agent") |
| 248 | +client = AnyAPI(api_key=result.secret) |
| 249 | +``` |
| 250 | +</CodeGroup> |
| 251 | + |
| 252 | +## Learn more |
| 253 | + |
| 254 | +- TypeScript package: [`@getanyapi/sdk` on npm](https://www.npmjs.com/package/@getanyapi/sdk) |
| 255 | +- Python package: [`getanyapi` on PyPI](https://pypi.org/project/getanyapi/) |
| 256 | +- Source and issues: [`getanyapi-com/sdks`](https://github.com/getanyapi-com/sdks) |
| 257 | +- Browse every API in the [API Reference](/api-reference/tiktok/tiktok-profile). |
0 commit comments