# `client` REST + WebSocket transport for the ElevenLabs platform. `ElevenLabsClient` exposes typed `fetchJson` / `fetchBinary` / `fetchStream` / `fetchMultipartJson` / `fetchMultipartBinary` / `openSocket` methods, plus internal retry-with-exponential-backoff that honours the `Retry-After` header. Every adapter in the package (`tts`, `stt`, `voices`, …) composes this single client so authentication, timeouts, retries, and event emissions live in exactly one place. _(no submodules)_ ## Purpose ElevenLabs offers a sprawling REST + WebSocket API surface. Without a shared transport, every adapter would duplicate the same error mapping, header injection, retry policy, and timeout handling. `ElevenLabsClient` solves that: it's the only piece of code in the package that calls `fetch`, and the only piece that knows how to map HTTP status codes onto typed errors. Adapters become thin domain remappers. ## Features - Five typed request shapes — JSON in/out, JSON in / binary out, JSON in / streaming out, multipart in / JSON out, multipart in / binary out. - WebSocket support via `openSocket()` for ElevenLabs's streaming-input TTS endpoints. - Built-in retry: exponential backoff (`initialDelay * 2^attempt`) with `Retry-After` honouring on 429 / 503 / 504 / network errors. - Per-request `AbortSignal` plus a per-call `timeoutMs` race. - Optional `LoggerLike` and `EventBusLike` for observability — emits `request-start`, `request-end`, `retry-attempt`, `rate-limit-hit`. - Caller-supplied `fetchImpl` and `webSocketImpl` for tests / edge runtimes. ## Usage: Basic Example ```ts import { ElevenLabsClient } from "@suaveplan/third-party-elevenlabs"; const client = new ElevenLabsClient({ apiKey: process.env.ELEVENLABS_KEY! }); const res = await client.fetchJson<{ voice_id: string }>({ method: "GET", path: "/v1/voices/abc", feature: "voices", operation: "get", }); console.log(res.body.voice_id, res.metadata.requestId); ``` ## Usage: Advanced Example ```ts import { ElevenLabsClient } from "@suaveplan/third-party-elevenlabs"; const client = new ElevenLabsClient({ apiKey: process.env.ELEVENLABS_KEY!, baseUrl: "https://eu.api.elevenlabs.io", timeoutMs: 60_000, maxRetries: 5, initialRetryDelayMs: 250, fetchImpl: customFetch, events: myBus, logger: myLogger, }); const ctrl = new AbortController(); const stream = await client.fetchStream({ method: "POST", path: "/v1/text-to-speech/voice-id/stream", feature: "tts", operation: "synthesize_stream", body: { text: "hello" }, accept: "audio/mpeg", signal: ctrl.signal, }); for await (const chunk of stream.body) { /* … */ } ``` ## API Reference - `new ElevenLabsClient(options: ElevenLabsClientOptions)` — constructor. - `fetchJson
(req: JsonRequest): Promise