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

@talkietalker/stream-sdk

v0.1.0

Published

TalkieTalker Stream server SDK for Node.js

Readme

TalkieTalkerStream Node.js Library

The TalkieTalkerStream Node library provides convenient access to the TalkieTalkerStream API from applications written in server-side JavaScript.

Use your secret key for server-side API calls and your publishable key in the browser. Never expose your secret key in client-side code.

Requirements

Node.js 18+ (LTS recommended).

Installation

npm install @talkietalker/stream-sdk

API keys

TalkieTalkerStream authenticates API requests using key pairs tied to your project:

| Key | Prefix | Where it runs | |-----|--------|---------------| | Secret key | sk_test_ / sk_live_ | Server only — REST API, token minting | | Publishable key | pk_test_ / pk_live_ | Browser / mobile — embed & watch flows | | Webhook secret | whsec_ | Server only — signature verification |

sk_test_ and pk_test_ target the sandbox. sk_live_ and pk_live_ target production. API and WebSocket URLs are inferred from the key prefix unless you set TALKIETALKER_STREAM_API_URL.

Environment variables

# Required for server-side usage
TALKIETALKER_STREAM_SECRET_KEY=sk_test_...

# Publishable key (browser + server validation)
TALKIETALKER_STREAM_PUBLISH_KEY=pk_test_...
# or, in Next.js / frontend projects:
NEXT_PUBLIC_TALKIETALKER_STREAM_PUBLISH_KEY=pk_test_...

# Webhook signature verification (server handlers)
TALKIETALKER_STREAM_WEBHOOK_SECRET=whsec_...

# Optional — self-hosted or local development override
TALKIETALKER_STREAM_API_URL=http://localhost:8080

Usage

Configure the client with your secret key, which is available in the TalkieTalkerStream Dashboard:

import TalkieTalkerStream from '@talkietalker/stream-sdk'

const tts = new TalkieTalkerStream({
  secretKey: process.env.TALKIETALKER_STREAM_SECRET_KEY!,
})

const stream = await talkietalkerstream.streams.create({
  title: 'Friday Night Stream',
  mode: 'broadcast',
  visibility: 'public',
})

Or resolve configuration from environment variables:

import { TalkieTalkerStream } from '@talkietalker/stream-sdk'

// Reads TALKIETALKER_STREAM_SECRET_KEY, TALKIETALKER_STREAM_PUBLISH_KEY, TALKIETALKER_STREAM_API_URL
const tts = new TalkieTalkerStream()

Usage with TypeScript

The package ships with TypeScript definitions. Import TalkieTalkerStream as a default or named import and instantiate with new TalkieTalkerStream():

import TalkieTalkerStream from '@talkietalker/stream-sdk'
import type { CreateStreamParams, StreamCreated } from '@talkietalker/stream-sdk'

const tts = new TalkieTalkerStream({ secretKey: 'sk_test_...' })

const params: CreateStreamParams = {
  title: 'Weekly standup',
  mode: 'room',
}

const stream: StreamCreated = await talkietalkerstream.streams.create(params)

Configuration

The client accepts a configuration object as its only argument:

const tts = new TalkieTalkerStream({
  secretKey: 'sk_test_...',
  publishKey: 'pk_test_...',
  baseURL: 'http://localhost:8080',
  maxRetries: 3,
})

| Option | Default | Description | |--------|---------|-------------| | secretKey | $TALKIETALKER_STREAM_SECRET_KEY | Server secret key. Required for authenticated requests. | | publishKey | $TALKIETALKER_STREAM_PUBLISH_KEY | Publishable key. Optional on the REST client; required for embed handler validation. | | baseURL | Inferred from key prefix | API base URL. Override for self-hosted deployments. | | maxRetries | 3 | Automatic retries on 429 rate-limit responses with exponential backoff. | | fetchImpl | globalThis.fetch | Custom fetch implementation (testing or edge runtimes). |

Per-request options

Pass a second argument to any resource method for per-request overrides:

await talkietalkerstream.streams.create(
  { title: 'Weekly standup' },
  { idempotencyKey: 'standup-2026-07-06' },
)

| Option | Description | |--------|-------------| | idempotencyKey | Safe retry key for POST requests. Cached 24h per project. | | unauthenticated | Skip the Authorization header. Used internally for public endpoints. |

Examining responses

Every successful API object includes a non-enumerable lastResponse property with request metadata:

const stream = await talkietalkerstream.streams.create({ title: 'Demo' })

stream.lastResponse.requestId  // correlates with X-Request-ID
stream.lastResponse.statusCode // HTTP status code

Streams

// Create
const created = await talkietalkerstream.streams.create({
  title: 'Friday Night Stream',
  description: 'Live coding session',
  mode: 'broadcast',           // 'broadcast' | 'room'
  visibility: 'public',        // 'public' | 'private'
  isPaid: true,
  price: 4.99,
  currency: 'USD',
  accessType: 'one_time_payment',
  isRecordingEnabled: true,
  thumbnailUrl: 'https://cdn.example.com/thumb.jpg',
})

// List your streams (authenticated)
const mine = await talkietalkerstream.streams.list({ status: 'live', page: 1, limit: 20 })

// List live public streams (no auth)
const live = await talkietalkerstream.streams.listLive({ page: 1, limit: 20 })

// Retrieve, update, delete
const detail = await talkietalkerstream.streams.retrieve(streamId)
await talkietalkerstream.streams.update(streamId, { title: 'Updated title' })
await talkietalkerstream.streams.del(streamId)

// Lifecycle
const started = await talkietalkerstream.streams.start(streamId)
const stopped = await talkietalkerstream.streams.stop(streamId)
const rotated = await talkietalkerstream.streams.rotateKey(streamId)

// Viewer access
const watch = await talkietalkerstream.streams.watch(streamId)

Projects

Manage projects and API keys for your account:

const project = await talkietalkerstream.projects.create({
  name: 'My App',
  slug: 'my-app',
  environment: 'sandbox',
  allowedOrigins: ['https://app.example.com'],
})

const projects = await talkietalkerstream.projects.list()
const one = await talkietalkerstream.projects.retrieve(project.id)
await talkietalkerstream.projects.update(project.id, { name: 'My App v2' })
await talkietalkerstream.projects.del(project.id)

// Nested API keys
const keys = await talkietalkerstream.projects.apiKeys.list(project.id)
const key = await talkietalkerstream.projects.apiKeys.create(project.id, {
  name: 'production',
  scopes: ['streams:read', 'streams:write'],
})
console.log(key.secret) // shown once — store securely
await talkietalkerstream.projects.apiKeys.revoke(project.id, key.id)

Webhooks

Register webhook endpoints on a project and manage deliveries:

const endpoint = await talkietalkerstream.webhooks.create(projectId, {
  url: 'https://example.com/webhooks/talkietalker-stream',
  enabledEvents: ['stream.*'],
})

const endpoints = await talkietalkerstream.webhooks.list(projectId)

await talkietalkerstream.webhooks.update(endpoint.id, {
  url: 'https://example.com/webhooks/v2',
  status: 'enabled',
})

await talkietalkerstream.webhooks.test(endpoint.id)
const deliveries = await talkietalkerstream.webhooks.listDeliveries(endpoint.id, { page: 1, limit: 20 })
await talkietalkerstream.webhooks.del(endpoint.id)

Recordings

const recordings = await talkietalkerstream.recordings.list({
  status: 'ready',
  page: 1,
  limit: 20,
})

const recording = await talkietalkerstream.recordings.retrieve(recordingId)
const byStream = await talkietalkerstream.recordings.retrieveByStream(streamId)

const { download_url, expires_at } = await talkietalkerstream.recordings.download(recordingId)

await talkietalkerstream.recordings.update(recordingId, {
  status: 'ready',
  durationSeconds: 3600,
})

await talkietalkerstream.recordings.del(recordingId)

Chat

Per-stream chat history and moderation:

const history = await talkietalkerstream.chat.listHistory(streamId, {
  before: '2026-06-12T16:00:00Z',
  limit: 50,
})

await talkietalkerstream.chat.deleteMessage(streamId, messageId)
await talkietalkerstream.chat.pinMessage(streamId, messageId)
await talkietalkerstream.chat.unpinMessage(streamId, messageId)

await talkietalkerstream.chat.banUser(streamId, userId, { reason: 'spam' })
await talkietalkerstream.chat.unbanUser(streamId, userId)

const { data: moderators } = await talkietalkerstream.chat.listModerators(streamId)
await talkietalkerstream.chat.addModerator(streamId, { userId: moderatorUserId })
await talkietalkerstream.chat.removeModerator(streamId, moderatorId)

// Build a WebSocket URL for live chat (pass JWT as token query param)
const wsUrl = talkietalkerstream.chat.websocketUrl(
  talkietalkerstream.baseURL,
  streamId,
  accessToken,
)

Embed tokens

Mint short-lived tokens for embedded room participants:

const token = await talkietalkerstream.embedTokens.create({
  resourceType: 'room',
  resourceId: roomId,
  participant: {
    name: 'Alice',
    role: 'host',
    userId: 'user_123',
  },
  ttlSeconds: 3600,
})

Error handling

Failed requests throw typed errors. Every error includes statusCode, code, and requestId when available:

import {
  TalkieTalkerStream,
  RateLimitError,
  ValidationError,
  AuthenticationError,
  NotFoundError,
} from '@talkietalker/stream-sdk'

try {
  await talkietalkerstream.streams.create({ title: '' })
} catch (err) {
  if (err instanceof ValidationError) {
    console.error(err.code, err.requestId)
  } else if (err instanceof RateLimitError) {
    console.error('retry after', err.retryAfter)
  } else if (err instanceof AuthenticationError) {
  } else if (err instanceof NotFoundError) {
  }
}

The client automatically retries 429 responses up to maxRetries times with exponential backoff.

Webhook signing

TalkieTalkerStream signs webhook events sent to your endpoint. You must pass the raw request body — not parsed JSON — to verifyWebhookSignature:

import { verifyWebhookSignature } from '@talkietalker/stream-sdk'

const event = verifyWebhookSignature({
  rawBody: req.body,                              // Buffer or string
  signatureHeader: req.headers['x-talkietalker-stream-signature'],
  secret: process.env.TALKIETALKER_STREAM_WEBHOOK_SECRET!,
})

The same helper is available from @talkietalker/stream-sdk/server for server-only bundles.

Server handlers

For embed token minting and webhook ingestion, use the framework-agnostic handlers or a ready-made adapter.

Framework adapters

Next.js (App Router)

// app/api/talkietalker-stream/[...path]/route.ts
import { talkieTalkerStreamHandlers } from '@talkietalker/stream-sdk/next'

export const { POST } = talkieTalkerStreamHandlers()

Routes:

  • POST /api/talkietalker-stream/token — mint embed token (requires X-TalkieTalker-Stream-Publish-Key header)
  • POST /api/talkietalker-stream/webhooks — receive signed webhook events

Express

import express from 'express'
import { talkieTalkerStreamRouter } from '@talkietalker/stream-sdk/express'

const app = express()
app.use('/api/talkietalker-stream', talkieTalkerStreamRouter())

Fastify

import Fastify from 'fastify'
import { talkieTalkerStreamPlugin } from '@talkietalker/stream-sdk/fastify'

const app = Fastify()
await app.register(talkieTalkerStreamPlugin, { prefix: '/api/talkietalker-stream' })

Custom framework integration

import { createTalkieTalkerStreamHandlers } from '@talkietalker/stream-sdk/handlers'

const handlers = createTalkieTalkerStreamHandlers({
  secretKey: process.env.TALKIETALKER_STREAM_SECRET_KEY,
  webhookSecret: process.env.TALKIETALKER_STREAM_WEBHOOK_SECRET,
  onWebhook: async (event) => {
    console.log('received', event.type)
  },
})

// POST /token
const token = await handlers.handleToken(
  { roomId: '...', participantName: 'Alice' },
  { publishKey: req.headers['x-talkietalker-stream-publish-key'] },
)

// POST /webhooks
const result = await handlers.handleWebhook(rawBody, signatureHeader)

Server utilities

import {
  TalkieTalkerStream,
  resolveServerConfig,
  mintEmbedToken,
  verifyWebhookSignature,
} from '@talkietalker/stream-sdk/server'

const config = resolveServerConfig()
const client = new TalkieTalkerStream({ secretKey: config.secretKey, baseURL: config.baseURL })

Package exports

| Import path | Purpose | |-------------|---------| | @talkietalker/stream-sdk | REST client, types, webhook verify, config helpers | | @talkietalker/stream-sdk/server | Server config, embed token minting, re-exports client | | @talkietalker/stream-sdk/handlers | Framework-agnostic token + webhook handlers | | @talkietalker/stream-sdk/next | Next.js App Router adapter | | @talkietalker/stream-sdk/express | Express router | | @talkietalker/stream-sdk/fastify | Fastify plugin |

Self-hosted

Point the SDK at your own API by setting baseURL or TALKIETALKER_STREAM_API_URL:

const tts = new TalkieTalkerStream({
  secretKey: 'sk_test_...',
  baseURL: 'http://localhost:8080',
})

WebSocket URLs are derived automatically from the REST base URL.

Security

  • Never expose sk_* secret keys in browser code, mobile apps, or version control.
  • Use pk_* publishable keys in the client; validate them server-side via the token handler.
  • Always verify webhook signatures before parsing the JSON body.
  • Import @talkietalker/stream-sdk/server only in server-side code.

License

MIT