Skip to main content
@gekoai/sdk is a thin, typed client for the Geko API. Zero runtime dependencies (built on the global fetch), dual ESM + CommonJS, bundled type declarations. Runs on Node 20+, Deno, Bun, and browsers (via a server-side proxy).

Install

The client

The client is namespaced by direction: text-to-speech under geko.tts, speech-to-text under geko.stt. Platform-level calls (models, health) sit on the client itself.
TTS and STT are two separately scaled GPU services, so they answer on two hosts. The SDK hides the split — one client, one API key, one credit balance, and each namespace routes to the right place. You never construct a second client.

Options

new Geko(options?) Both hosts share the same credentials, timeout, and retry policy. geko.baseUrl and geko.sttBaseUrl read back the resolved values.

Text-to-speech

geko.tts.create(params)

Synthesize speech. Returns a Promise<ArrayBuffer> of raw WAV bytes (24 kHz, PCM16, mono).
Turn the bytes into a file or a playable blob — see Playing & saving audio.

geko.tts.stream(params)

Stream synthesis sentence-by-sentence to start playback sooner on long text. Returns an async iterable of WAV ArrayBuffers — one per chunk, each independently playable. Same params as create().
Streams aren’t retried (a partial stream can’t be replayed); use signal to cancel and a per-call timeout to bound the whole stream. Under the hood it consumes the framed wav-frames-v1 protocol from POST /v1/tts/stream.

geko.tts.voices(model?, options?)

List the voices for a model. Returns { model, voices: Voice[] }.

Speech-to-text

geko.stt.transcribe(params)

Transcribe audio. Returns a Promise<Transcription> — the transcript plus timing and the credits actually charged. Pass exactly one of audio (uploads the bytes) or url (the server fetches it). Passing both, or neither, throws a TypeError before any request goes out.
There is deliberately no language parameter — Kazakh and Russian share one output vocabulary, so the model is never told which to expect and a speaker can switch mid-sentence. See the STT overview. Audio uploads as an octet-stream rather than multipart, which keeps the request body replayable — so transcriptions still benefit from the automatic retry on transient failures.

geko.stt.models(options?)

List the STT models the endpoint serves, with the price per audio-second. Returns { data: SttModel[] }.
This is not the same as geko.models(). The two hosts each serve a /v1/models with a different shape — use geko.stt.models() for transcription models and geko.models() for synthesis models and their voices.

geko.stt.estimateCredits(audioSeconds)

Price a file before you spend anything. Pure arithmetic — no request is made — and it matches the server’s rounding, ceil(seconds × 2.5).

Platform

geko.models(options?)

List every text-to-speech model and its voices. Returns { data: Model[] }.

geko.health(options?)

Text-to-speech service probe. Returns { status, models: string[] }.
The read methods accept an options object of { signal?, timeout? }.

Types

Response types describe the server contract; like most thin SDKs, JSON bodies are not re-validated at runtime.

Timeouts, cancellation & retries

Covered in depth in Errors & retries. In short: transient failures (network, timeout, 5xx) retry with backoff; 429 never does; pass an AbortSignal or a per-call timeout to control individual requests.

Bring your own fetch

Useful for proxies, logging, or tests. The SDK always calls fetch as a free function, so undici’s global keeps its binding and your custom fetch keeps its own.

Next steps

Playing & saving audio

Turn the WAV bytes into files, playback, or other formats.

Errors & retries

Typed errors, automatic retries, timeouts, and cancellation.

Speech-to-text

Response fields, audio formats, and accuracy.

CLI

say and transcribe from your terminal.