npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

kasookoo-server-sdk

v0.1.0-beta.4

Published

Official Node.js/TypeScript server-side SDK for Kasookoo — create call intents and other backend operations.

Readme

kasookoo-server-sdk

Node.js / TypeScript SDK for Kasookoo's server-side API. Server-only — it holds your organization's secret key, which must never reach a browser.

This SDK only creates call intents — it doesn't place calls itself. That half happens on the frontend, in either of two places:

  • kasookoo-sdk's initSipCall({ phoneNumber, intentId, clientSecret }) (readme.io: Calls) — for a custom call UI you build yourself.
  • kasookoo-click-to-call-widget's (readme.io docs) <kasookoo-dialer> — a drop-in call button/dial pad. It doesn't call initSipCall() directly itself; instead, it fetches an intent on its own from a route you give it (intentEndpoint, passed to its init()), then dials with what that route returns.

Either way, the shape is the same: your frontend asks your backend for a call intent, your backend creates it with this SDK, and your route must respond with the two fields the frontend needs to actually place the call: intentId and clientSecret. Nothing else you put in that response matters to either integration.

npm package · readme.io docs

Install

npm install kasookoo-server-sdk

Usage

import { Kasookoo } from "kasookoo-server-sdk"

const kasookoo = new Kasookoo({
  secretKey: process.env.KASOOKOO_SECRET_KEY!,
})

const intent = await kasookoo.callIntents.create({
  subject: "Website visitor", // must match the `subject` your frontend passes to init() — see below
  phoneNumber: "+18005551234",
  maxDurationSeconds: 300, // optional
})

callIntents.create() sends your secret key to Kasookoo and returns:

interface CallIntent {
  intentId: string        // unique id for this call intent
  clientSecret: string    // short-lived secret for the frontend — hand this off, never the org secret key
  subject: string
  phoneNumber: string
  expiresIn: number       // seconds until clientSecret expires if unused
  maxDurationSeconds: number
  status: "requires_dial" | string
}

Respond from your route with at least intentId and clientSecret — that's the whole contract, whichever frontend integration is consuming it (see above): kasookoo-sdk's initSipCall(), or kasookoo-click-to-call-widget's intentEndpoint. Your org's secret key never needs to leave the server.

Keep subject in sync with the frontend's init()

The subject you pass here must be the exact same value the frontend passed to init() — kasookoo-sdk's KasookooClient.init({ subject }) or kasookoo-click-to-call-widget's KasookooClickToCall.init({ subject }). Kasookoo checks the two against each other and rejects the call intent if they don't match (surfaced as a KasookooApiError — see Errors below), so always pass subject here explicitly, kept identical to whatever your frontend's init() call used — don't assume it's implied or optional just because the frontend already sent one.

Configuration

| Option | Type | Default | Description | |---|---|---|---| | secretKey | string | required | Your organization's secret key. | | baseUrl | string | https://sdk-test.kasookoo.ai | API base URL. | | timeoutMs | number | 10000 | Request timeout in milliseconds. | | fetch | typeof fetch | global fetch | Override for testing, or on Node < 18. |

Example: a mini Express app

import express from "express"
import { Kasookoo } from "kasookoo-server-sdk"

const kasookoo = new Kasookoo({ secretKey: process.env.KASOOKOO_SECRET_KEY })
const app = express().use(express.json())

app.post("/my-api/call-intent", async (req, res) => {
  const { phoneNumber, subject } = req.body
  try {
    const { intentId, clientSecret } = await kasookoo.callIntents.create({ subject, phoneNumber })
    res.json({ intentId, clientSecret })
  } catch {
    res.sendStatus(502)
  }
})

app.listen(3000)

Point your frontend's intentEndpoint at /my-api/call-intent. Protect this route with authentication or rate limiting before going live.

Errors

The SDK throws two error types, both exported from the package:

import { KasookooApiError, KasookooConfigError } from "kasookoo-server-sdk"

KasookooApiError

Kasookoo rejected the request, or couldn't be reached.

| Property | Description | |---|---| | message | Human-readable description (the API's own message when it sent one). | | status | HTTP status code. 0 if no response was received (network error or timeout). | | code | Error code from the API, if any. The SDK sets "timeout" and "network_error" itself when status is 0. | | details | The full parsed error response body, if any. |

KasookooConfigError

Invalid SDK usage, thrown before any network call: a missing secretKey, no fetch available (Node < 18 without the fetch option), or an empty subject / phoneNumber passed to callIntents.create().

Handling them

try {
  await kasookoo.callIntents.create({ subject, phoneNumber })
} catch (err) {
  if (err instanceof KasookooApiError) {
    console.error(err.status, err.code, err.message)
  } else if (err instanceof KasookooConfigError) {
    console.error(err.message)
  } else {
    throw err
  }
}

A subject that doesn't match the one your frontend passed to init() is rejected by Kasookoo and surfaces as a KasookooApiError.

Requirements

  • Node.js 18+ (for global fetch; pass your own via the fetch option on older runtimes).