SDKs

Talkif ships two official clients, generated from the same API definition that produces this reference — so every endpoint, parameter and response type in the API Reference exists in both, with the same names. When the API changes, the SDKs change with it.

SDKTypeScript / Node.jsPython
Package@talkif/sdk on npmtalkif on PyPI
RuntimeNode 18+, Bun, Deno, modern browsers (server-side recommended — keep your API key out of browsers)Python 3.10+
ClientTalkifClientTalkif (sync) and AsyncTalkif (async)
SourceTalkif-ai/talkif-typescriptTalkif-ai/talkif-python

For voice calls from a web page — a “talk to our agent” button — use the browser SDK — see Web calls — not these. These clients are for the control API: placing phone calls, managing flows, contacts, campaigns, numbers and billing from your backend.

Using Claude Code, Codex or Cursor to write the integration? Install the Talkif Agent Skills — they teach the agent these SDKs and every endpoint.

Install

npm install @talkif/sdk

Authenticate

Both clients take an API key as token and send it as a Bearer header on every request. Create one under Developer → Credentials in the dashboard — see Authentication for scopes, rotation and where keys are safe to live. Read it from the environment; never hard-code it.

import { TalkifClient } from "@talkif/sdk";
const client = new TalkifClient({ token: process.env.TALKIF_API_KEY });

token also accepts a function, so a key you rotate at runtime (or fetch from a secrets manager) is picked up on the next request without rebuilding the client.

Place a call

The same request as POST /api/v1/calls in the Quickstart: the flow to run, a number you own to call from, the provider that number belongs to, and the destination.

const result = await client.calls.makeCall({
flowId: "550e8400-e29b-41d4-a716-446655440000",
fromNumber: "+15559876543",
providerId: "550e8400-e29b-41d4-a716-446655440000",
toNumber: "+15551234567",
});
if (result.type === "initiated") {
console.log("placing call", result.callId);
} else {
// your account is at its concurrent-call limit; the call is queued
console.log(`queued at position ${result.position}`);
}

The response is a union: initiated (HTTP 201, the call is being placed) or queued (HTTP 202). Both shapes are in How a call works.

Page through lists

List endpoints (calls.getCallHistory, contacts.listContacts, campaigns.listCampaigns, …) use limit/offset and return a pager. (In the API the call list is GET /calls; the 0.1.x SDKs still expose it as getCallHistory / get_call_history until the next SDK release.) Iterate it and the client fetches the next page for you; you never handle offset yourself.

const history = await client.calls.getCallHistory({
status: "completed",
startDate: "2026-09-01T00:00:00Z",
});
for await (const call of history) {
console.log(call.id, call.direction, call.duration);
}

If you’d rather control paging — to show a page in a UI, say — pass limit and offset explicitly and read the page’s items (calls, contacts, …) and meta (total count) without iterating.

Handle errors

Non-2xx responses raise a typed error per status. The body carries the platform’s error code — that’s the field to branch on, not the message.

import { Talkif, TalkifError } from "@talkif/sdk";
try {
await client.calls.makeCall({ /* … */ });
} catch (err) {
if (err instanceof Talkif.PaymentRequiredError) {
// insufficient balance — top up or enable auto-recharge
} else if (err instanceof Talkif.TooManyRequestsError) {
// rate limited — back off and retry
} else if (err instanceof TalkifError) {
console.error(err.statusCode, err.body);
} else {
throw err;
}
}

Retries are built in: both clients retry on 408, 429 and 5xx responses with exponential backoff — twice by default (maxRetries / max_retries, per client or per call). Timeouts default to 60 seconds and are set the same way. Because a retried POST /calls could place a second call if the first actually succeeded, keep maxRetries at its default and check for the call in history before re-issuing a request that timed out.

Async Python

Every method exists on AsyncTalkif with the same name and arguments.

Python (asyncio)
import asyncio
from talkif import AsyncTalkif
client = AsyncTalkif(token=os.environ["TALKIF_API_KEY"])
async def main():
active = await client.calls.get_active_calls()
print(len(active.calls), "active")
asyncio.run(main())

Versioning

SDK versions follow the API: a new endpoint or field is a minor release, a removed or renamed one is a major. Pin a minor range in production (^0.1 / ~=0.1) and read the release notes on the repo before moving majors. Both packages are published only from a tagged release, never from a branch.

What’s next