ListenHubSDKs & CLI
JavaScript SDK

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 @types package 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-sdk

Two 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.

OpenAPIClientListenHubClient
AuthAPI key (Authorization: Bearer)OAuth user access token
Runs inServers, scripts, CIUser-facing apps, on behalf of a signed-in user
Base URLhttps://api.marswave.ai/openapihttps://api.listenhub.ai/api
Acts asYour account / key ownerThe 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 to data directly — you never see the envelope.
  • On a non-zero code or an HTTP error, the method throws a ListenHubError carrying status, code, and requestId.
  • On 429 Too Many Requests, the client reads the Retry-After header and retries automatically, up to maxRetries (default 2).

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

On this page