設定
両方の SDK クライアントで base URL、タイムアウト、リトライを設定し、レスポンスのアンラップ、ListenHubError、429 の自動リトライの挙動を理解します。
どちらの SDK クライアントも、コンストラクタでオプションオブジェクトを受け取ります。2 つはオプション名もレスポンスの扱いも共通ですが、デフォルト値は異なります — OpenAPIClient はサーバーサイドの処理向けに作られており、タイムアウトが長めです。このページでは、すべてのオプション、クライアントが自動で展開するレスポンスエンベロープ、エラーが ListenHubError としてどう現れるか、429 の自動リトライ、そして SDK がまだラップしていないエンドポイントを呼ぶための client.api エスケープハッチを解説します。
オプション
ListenHubClient は ClientOptions を、OpenAPIClient は OpenAPIClientOptions を受け取ります。すべてのフィールドは省略可能です。
| オプション | 型 | OpenAPIClient のデフォルト | ListenHubClient のデフォルト |
|---|---|---|---|
apiKey | string | 環境変数 LISTENHUB_API_KEY | —(該当なし) |
accessToken | string | (() => string | undefined) | —(該当なし) | なし(匿名) |
baseURL | string | https://api.marswave.ai/openapi | https://api.listenhub.ai/api |
timeout | number(ミリ秒) | 60000 | 30000 |
maxRetries | number | 2 | 2 |
認証情報はクライアントによって異なります:OpenAPIClient は apiKey で、ListenHubClient は accessToken で認証します。それぞれの取得方法は 認証 を参照してください。
baseURL
クライアントの宛先を特定の API ホストに向けます。デフォルトは本番環境を指しているため、手動で設定することはほとんどありません。baseURL を渡さなかった場合、各クライアントはフォールバックとして環境変数も読み取ります:
OpenAPIClient→LISTENHUB_OPENAPI_URLListenHubClient→LISTENHUB_API_URL
明示的に指定した baseURL オプションは、常に環境変数より優先されます。
import { OpenAPIClient } from '@marswave/listenhub-sdk';
const client = new OpenAPIClient({
baseURL: 'https://api.marswave.ai/openapi',
});accessToken(ListenHubClient)
accessToken は静的な文字列、またはゲッター関数 () => string | undefined を受け付けます。ゲッターを渡すと SDK がリクエストごとにそれを呼び出すため、長命なクライアントでも作り直すことなく常に現在のトークンを送信できます。トークンが時間とともに更新される場合は、この形を推奨します。
import { ListenHubClient } from '@marswave/listenhub-sdk';
// Static token — fine for short-lived clients
const client = new ListenHubClient({ accessToken: tokens.accessToken });
// Getter — called before each request; return the freshest token you hold
const live = new ListenHubClient({ accessToken: () => store.accessToken });トークン更新のライフサイクル(いつ、どのように新しいトークンを発行するか)は 認証 にあります。
apiKey(OpenAPIClient)
apiKey はサーバーサイド処理用の認証情報です。明示的に渡すか、省略してコンストラクタに環境変数の LISTENHUB_API_KEY を読み取らせます。どちらもない場合、コンストラクタは例外を投げます。
import { OpenAPIClient } from '@marswave/listenhub-sdk';
const client = new OpenAPIClient({ apiKey: process.env.LISTENHUB_API_KEY });API キーはアカウントへのフルアクセス権を持つ機密情報です。サーバーサイドに保管し、ブラウザやモバイルのコードに含めて配布しないでください。ユーザー向けアプリでは OAuth を使う ListenHubClient を利用し、各リクエストがユーザー自身のアカウントで実行されるようにします。
timeout
リクエストごとのタイムアウト(ミリ秒)。これを超えたリクエストは中断され、reject されます。サーバーサイドの生成呼び出しは長時間かかることがあるため、OpenAPIClient のデフォルトは 60000(60 秒)です。ListenHubClient のデフォルトは 30000(30 秒)です。
const client = new OpenAPIClient({ timeout: 120_000 }); // 2 minutesこのタイムアウトは HTTP リクエスト自体に適用されるもので、長時間実行される生成ジョブには適用されません。生成は非同期です — 作成系の呼び出しは episodeId や taskId をすぐに返し、結果はポーリングして取得します。クイックスタート の作成&ポーリングのループを参照してください。
maxRetries
429 Too Many Requests のレスポンスに対して、クライアントが諦めるまでにリトライする回数です。デフォルトは 2 です。0 にするとリトライを無効化できます。リトライされるのは 429 だけで、他のエラーステータスは即座に例外を投げます。下記の 429 レート制限のリトライ を参照してください。
const client = new OpenAPIClient({ maxRetries: 0 }); // fail fast, no retryレスポンスのアンラップ
ListenHub のレスポンスはすべてエンベロープにラップされています:
{ "code": 0, "message": "", "data": { } }code が 0 なら成功で、0 以外の code はエラーです。どちらのクライアントも afterResponse フックでエンベロープを処理するため、コード側では data を直接扱えます:
code 0の場合、メソッドはdataを返します — ラッパーが見えることはありません。codeが0以外の場合、メソッドはエンベロープのcode、message、request_idを持つListenHubErrorを投げます。204 No Contentのレスポンス(および JSON でないボディ)はそのまま素通りします。
// The SDK returns data directly — no envelope to peel
const { items } = await client.listSpeakers({ language: 'en' });一部のメソッドは、ストリーミングやバイナリを返すため、アンラップ済みの JSON ではなく生の Response を返します — たとえば TTS 音声(tts、audioSpeech)やテキストストリーム系のエンドポイントです。これらは例外で、それ以外はすべて data を返します。
エラー処理
リクエストが失敗したとき — 認証情報の拒否、バリデーションエラー、0 以外の code、HTTP のエラーステータス — メソッドは ListenHubError を投げます。これを捕捉して、フィールドを確認してください:
| フィールド | 型 | 意味 |
|---|---|---|
status | number | HTTP ステータスコード(例:401、429、500) |
code | string | エンベロープに含まれるバックエンドのエラーコード。JSON でない失敗の場合は GATEWAY_ERROR / UNKNOWN_ERROR |
message | string | 人間が読めるエラーメッセージ |
requestId | string | undefined | リクエスト識別子 — サポートに問い合わせる際に添えてください |
import { OpenAPIClient, ListenHubError } from '@marswave/listenhub-sdk';
const client = new OpenAPIClient();
try {
const sub = await client.getSubscription();
console.log(sub);
} catch (err) {
if (err instanceof ListenHubError) {
// Structured error from the API
console.error(`[${err.status}] ${err.code}: ${err.message}`);
if (err.requestId) console.error(`request ${err.requestId}`);
if (err.status === 401 || err.status === 403) {
// Credential rejected — rotate the API key, or refresh the OAuth token
}
} else {
// Network failure, timeout, or other non-API error
throw err;
}
}ListenHubError は JSON でない失敗に対しても投げられます。ゲートウェイやプロキシが HTML のエラーページを返した場合は code: 'GATEWAY_ERROR' として現れ(ページの <title> がメッセージになります)、それ以外のパースできないものは code: 'UNKNOWN_ERROR' として現れます。どちらの場合も status は HTTP ステータスを反映します。
429 レート制限のリトライ
429 Too Many Requests のレスポンスは自動でリトライされるため、リトライ処理を自分で書く必要はありません。クライアントの動作は次のとおりです:
Retry-Afterヘッダーを読み、待機時間を決めます。- 最大
maxRetries回(デフォルト2)リトライします。 - すべてのリトライを使い切った場合、
status: 429のListenHubErrorを投げます。
このため、短時間のレート制限はたいてい自動的に解消し、エラーとして表面化しません。429 を即座に例外にしたい場合は maxRetries: 0 を設定してください。この経路をたどるのは 429 だけで、他のエラーステータスはすべて最初のレスポンスで例外を投げます。
client.api エスケープハッチ
ListenHubClient は、内部で使っている ky インスタンスを client.api として公開しています。SDK がまだラップしていないエンドポイントを呼ぶのに使います — 設定済みのクライアントを再利用するため、同じ認証ヘッダー、base URL、エンベロープのアンラップ、429 のリトライがそのまま適用されます。
import { ListenHubClient } from '@marswave/listenhub-sdk';
const client = new ListenHubClient({ accessToken: tokens.accessToken });
// Paths are relative to baseURL — no leading slash (ky requirement)
const data = await client.api.get('v1/some/new-endpoint').json();
const created = await client.api
.post('v1/some/new-endpoint', { json: { foo: 'bar' } })
.json();client.api に渡すパスは baseURL からの相対パスで、先頭に / を付けてはいけません — これは ky の要件です。/v1/... ではなく v1/... を使ってください。
このエスケープハッチが使えるのは ListenHubClient です。OpenAPIClient では型付きメソッドの利用を優先してください。カバーされていないエンドポイントが必要な場合は、OpenAPI リファレンス を参照し、同じ Authorization: Bearer ヘッダーを付けて自前の HTTP クライアントから呼び出してください。