TypeScript SDK
The official @qalyb/sdk package — fully typed, zero runtime deps, and it runs anywhere modern JavaScript runs (Node 18+, Bun, Deno, Cloudflare Workers, browsers via your backend). Everything you can do in the dashboard, from your own code.
Install
One package, no runtime dependencies — use whichever package manager you already have:
# npm
npm install @qalyb/sdk
# pnpm
pnpm add @qalyb/sdk
# yarn
yarn add @qalyb/sdkInitialize
Pass your API key explicitly. The client validates every response with Zod, so type-narrowing works without unsafe casts.
import { Qalyb } from '@qalyb/sdk';
const qalyb = new Qalyb({
apiKey: process.env.QALYB_API_KEY!,
// Optional overrides:
// baseUrl: 'https://api.qalyb.ai',
// fetch: customFetch, // any fetch-compatible impl
});Models
The model namespaces give you direct access to TTS, STT, LLM, and the voice catalog — no agents required.
qalyb.tts.create
import fs from 'node:fs';
const audio = await qalyb.tts.create({
text: 'Marhaba! Welcome to Qalyb.',
voiceId: 'voice_amal_ar',
speed: 1.0,
stability: 0.5,
similarity: 0.75,
format: 'mp3',
});
fs.writeFileSync('hello.mp3', Buffer.from(audio));qalyb.stt.create
import fs from 'node:fs';
const result = await qalyb.stt.create({
audio: fs.readFileSync('./call.wav'),
audioMimeType: 'audio/wav',
language: 'ar',
});
console.log(result.text);
console.log(result.segments);qalyb.llm.chat
const reply = await qalyb.llm.chat({
messages: [
{ role: 'system', content: 'You are a friendly receptionist.' },
{ role: 'user', content: 'Can I book an appointment?' },
],
temperature: 0.4,
});
console.log(reply.message.content);
console.log(reply.usage.promptTokens, reply.usage.completionTokens);qalyb.voices
// List
const { voices } = await qalyb.voices.list();
// Get one
const amal = await qalyb.voices.get('voice_amal_ar');
// Clone
const cloned = await qalyb.voices.clone({
audio: fs.readFileSync('./brand-sample.wav'),
name: 'Acme Brand Voice',
language: 'ar',
gender: 'female',
consent: true,
});Agents
The qalyb.agents namespace covers the full agent lifecycle plus call control. Outbound and web calls are scoped under the agent that runs them.
// Create
const agent = await qalyb.agents.create({
name: 'Bookings Concierge',
personaId: 'p47e2c12-8b8d-4f8e-9b16-7c1a8f9c3a01',
description: 'Books appointments at Acme Clinic.',
instructions: {
systemPrompt: 'You are a friendly receptionist...',
greeting: 'Marhaba! Welcome to Acme Clinic.',
},
});
// CRUD
const { agents } = await qalyb.agents.list();
const fresh = await qalyb.agents.get(agent.id);
await qalyb.agents.update(agent.id, { description: 'Updated copy.' });
await qalyb.agents.delete(agent.id);
// Place an outbound call
const call = await qalyb.agents.startCall(agent.id, {
phoneNumber: '+971501234567',
variables: { customer_name: 'Layla' },
});
// Start a web call (returns LiveKit credentials for the browser)
const session = await qalyb.agents.startWebCall(agent.id, {
variables: { customer_name: 'Layla' },
});
// List recent calls for the agent
const { calls } = await qalyb.agents.listCalls(agent.id, { limit: 20 });
// Top-level call lookup (works for any call id)
const detail = await qalyb.calls.get(call.id);Error handling
Every API error is thrown as a QalybApiError with a typed status, code, and human-readable message. Anything else is a network or runtime error and should bubble up.
import { Qalyb, QalybApiError } from '@qalyb/sdk';
try {
await qalyb.agents.startCall('agt_abc123', {
phoneNumber: '+1',
});
} catch (err) {
if (err instanceof QalybApiError) {
console.error(err.status, err.code, err.message);
} else {
throw err;
}
}Module map
| Namespace | Methods | Endpoints |
|---|---|---|
qalyb.tts | create | POST /v1/tts |
qalyb.stt | create | POST /v1/stt |
qalyb.llm | chat | POST /v1/llm/chat |
qalyb.voices | list, get, clone | GET /v1/voices, GET /v1/voices/:id, POST /v1/voices/clone |
qalyb.agents | create, list, get, update, delete, startCall, startWebCall, listCalls | /v1/agents, /v1/agents/:id/calls, /v1/agents/:id/web-call |
qalyb.calls | get | GET /v1/calls/:id |
Every method mirrors the REST surface documented in the API reference.
