JavaScript SDK
A typed JavaScript/TypeScript client for the ListenHub API, with two clients for API-key and OAuth authentication.
@marswave/listenhub-sdk is the official JavaScript/TypeScript client for the ListenHub API. It is a flat client — every endpoint is a method directly on the client object — over a ky-based HTTP layer that unwraps the standard { code, message, data } envelope and retries 429 responses for you.
- ESM only, ships its own TypeScript types — no
@typespackage needed. - Node.js >= 20. Works in the browser too when you authenticate with OAuth user tokens.
- One dependency (
ky), so it stays small in a bundle.
Install
npm i @marswave/listenhub-sdkTwo clients
The SDK exports two clients. They share the same response handling and retry behavior; they differ in how they authenticate and which API surface they target. Pick one based on where your code runs.
OpenAPIClient | ListenHubClient | |
|---|---|---|
| Auth | API key (Authorization: Bearer) | OAuth user access token |
| Runs in | Servers, scripts, CI | User-facing apps, on behalf of a signed-in user |
| Base URL | https://api.marswave.ai/openapi | https://api.listenhub.ai/api |
| Acts as | Your account / key owner | The logged-in user |
Use OpenAPIClient for server-side and automation work. It is the public OpenAPI product: pass an API key created at listenhub.ai/settings/api-keys, or set the LISTENHUB_API_KEY environment variable and construct it with no arguments.
Use ListenHubClient when each request must run under an individual user's account — an interactive app where users sign in with OAuth. Its accessToken accepts a static string or a getter function () => string | undefined, called before every request so you can hand it a token that refreshes over time.
Treat API keys as secrets. Keep them server-side — never ship an API key in browser or mobile client code. For user-facing apps, authenticate with OAuth so each request runs under the user's own account.
Hello world
Construct a client, list speakers, and start a flow speech (text-to-speech) episode. This uses OpenAPIClient and reads the key from LISTENHUB_API_KEY.
import { OpenAPIClient } from '@marswave/listenhub-sdk';
const client = new OpenAPIClient(); // reads LISTENHUB_API_KEY
const { items: speakers } = await client.listSpeakers({ language: 'en' });
const { episodeId } = await client.createFlowSpeech({
sources: [{ type: 'text', content: 'Hello world' }],
speakers: [{ speakerId: speakers[0].speakerId }],
});Generation is asynchronous: createFlowSpeech returns an episodeId immediately. Poll getFlowSpeech(episodeId) until processStatus leaves pending to get the audio URL. See Quickstart for the full create-and-poll loop.
How responses work
Every ListenHub response is wrapped in { "code": 0, "message": "", "data": { … } }, where a non-zero code signals an error. Both clients handle this for you:
- On
code 0, the method resolves todatadirectly — you never see the envelope. - On a non-zero
codeor an HTTP error, the method throws aListenHubErrorcarryingstatus,code, andrequestId. - On
429 Too Many Requests, the client reads theRetry-Afterheader and retries automatically, up tomaxRetries(default2).
For anything the SDK does not wrap yet, ListenHubClient exposes the underlying ky instance as client.api — an escape hatch that reuses the same auth, base URL, and retry behavior (OpenAPIClient does not expose it):
import { ListenHubClient } from '@marswave/listenhub-sdk';
const userClient = new ListenHubClient({ accessToken });
const me = await userClient.api.get('v1/users/me').json();Next steps
Quickstart
Install, authenticate, and create your first episode end to end.
Authentication
API keys vs. OAuth tokens, the accessToken getter, and where credentials live.
Configuration
Base URL, timeout, retries, and environment variables for both clients.
Reference
Every client method grouped by product: podcast, TTS, image, music, video, and more.
Examples
Runnable scripts for podcasts, explainer videos, slides, images, music, and video.
OpenAPI reference
Endpoint-level detail: paths, parameters, enums, and response shapes.