SDKs
There is nothing to install, and that is deliberate.
A handful of GET endpoints with query parameters is not enough surface to justify a package in five
languages —
each of which would lag the API, need its own release, and hide the two things that actually matter: the
limit headers and how you retry.
What you get instead:
- An OpenAPI 3.1 document that any generator consumes, if you want types — see OpenAPI.
- A worked client per language below, short enough to read in one sitting and paste into your own code.
What a client should do
- Send the key as a header, never in the query string. Query strings end up in logs and referrers.
- Tell the 429s apart. Spending this minute's credits is transient and wants a short retry;
running out of the month's credits is not and wants an error. The body's
codedistinguishes them:insufficient_creditsis the one not to retry. The logic is here. - Surface
from_clamped. Otherwise a plan boundary is indistinguishable from an empty corpus. Archive depth. - Check
partialandcoveragebefore caching a negative. A200with few results andpartial: trueis a degraded index, not a quiet news day. Reading completeness. - Switch on
code, not on prose. Every error body is JSON with a stablecode, including401,402and429. Error bodies. - Ask for large pages.
limit=100where you can — each page is a billed request. - Do not retry a
404or a zero-result response. Neither is a failure.
If you are writing an agent rather than a client, you probably want MCP instead — the model reads the tool descriptions and makes these choices itself.
Comparing the five, honestly
| Language | Dependencies | Async | Timeout set by default | Generated types available |
|---|---|---|---|---|
| curl | jq, for the examples that parse JSON | No — one call per invocation | No — add --max-time yourself | No |
| TypeScript | None for the client; openapi-typescript is dev-only | Yes, natively | No — add one explicitly | Yes, from the spec |
| Python | httpx | Optional — sync and async variants shown | Yes, 30s | No — hand-write a TypedDict, or generate one separately |
| Go | None — standard library only | Via goroutines, not built into the client | Yes, 30s | Yes, via oapi-codegen |
| Rust | reqwest, serde, tokio, thiserror | Yes, natively (async fn) | Yes, 30s | No — the structs above are hand-written |
The honest takeaway is that the languages with a mainstream code generator for OpenAPI (TypeScript, Go) get typed requests almost for free, and the ones without a commonly-used one for this shape of spec (Python, Rust) are better served hand-writing the dozen fields these six endpoints actually return than pulling in a heavier generator dependency for it.
Questions this page actually gets
- Why is there no official package on PyPI, npm or crates.io?
- Because publishing one creates a second thing to version, and it would lag the API the moment a field is added to a response — the worked examples on this page are current with the OpenAPI document by construction, since they are read from it, not maintained separately against it.
- Which language should I start with if I have no preference?
- curl, to see the raw shapes and headers with nothing hiding them, then whichever of the other four matches the language your project is already in — the retry logic is the same decision in every one of them, just spelled differently.
- Do any of these examples handle the MCP endpoint instead of REST?
-
Each language page ends with a short MCP example alongside its REST client, calling the same
list_storiestool the REST examples call as/stories— useful for comparing the two surfaces directly rather than reading the MCP overview in the abstract.