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 🙏

© 2025 – Pkg Stats / Ryan Hefner

@coloop-ai/recall-sdk

v0.9.0

Published

Type-safe SDK for the Recall.ai meeting bot API, generated from the provider's endpoint references.

Readme

@coloop-ai/recall-sdk

npm version npm downloads npm bundle size License: MIT TypeScript GitHub stars

Type-safe client bindings for the Recall.ai meeting bot API. Operations are generated from the provider's OpenAPI fragments and wrapped in an ergonomic SDK.

⚠️ This project is maintained by Coloop and is not affiliated with or endorsed by Recall.ai — review their API terms before use.

Installation

npm install @coloop-ai/recall-sdk

Quick start

import { RecallSdk } from '@coloop-ai/recall-sdk'

const recall = new RecallSdk({
  apiKey: process.env.RECALL_API_KEY!,
  timeoutMs: 10_000, // abort requests that hang for 10s
  // baseUrl: 'https://eu-central-1.recall.ai', // optionally target a different region
})

const bot = await recall.bot.create({
  meeting_url: 'https://zoom.us/j/123456789',
  bot_name: 'Demo bot',
})

const bots = await recall.bot.list({
  status: ['ready', 'joining_call'],
})
console.log(bots.results?.map((entry) => entry.id))

await recall.bot.update(bot.id, {
  metadata: { source: 'docs-example' },
})

const now = new Date().toISOString()

const events = await recall.calendar.listEvents({
  start_time__gte: now,
})

if (events.next) {
  const moreEvents = await recall.calendar.listEvents({
    start_time__gte: now,
    cursor: events.next,
  })
}

const nextEvent = events.results?.[0]
if (nextEvent) {
  await recall.calendar.scheduleBot(nextEvent.id, {
    deduplication_key: nextEvent.id,
    bot_config: {
      join_offset: 60,
    },
  })
}

Once a recording finishes processing you can mirror what Recall surfaces in the dashboard:

const recording = await recall.recording.retrieve(bot.recording_id!)

if (recording.shortcuts?.video_mixed?.id) {
  const video = await recall.video.mixed.retrieve(
    recording.shortcuts.video_mixed.id,
  )
  console.log('Download mixed video from', video.data.download_url)
}

const audioSeparate = await recall.audio.separate.list({
  recording_id: recording.id,
})
const firstParticipantTrack = audioSeparate.results?.[0]
if (firstParticipantTrack) {
  await recall.audio.separate.update(firstParticipantTrack.id, {
    metadata: { exported_by: 'sample-app' },
  })
}

The RecallSdk automatically adds the Token prefix to your API key when missing, throws RecallSdkError for non-success responses, and returns the typed response payload for each call, optionally aborting hung requests (and raising a RecallSdkTimeoutError) when timeoutMs is configured.

Error handling

Every helper raises a RecallSdkError when the Recall API responds with a non-2xx status. The error exposes the HTTP status code, Recall-specific code / detail fields (when present), original response/request objects, and the parsed payload so you can make retry vs. fail-fast decisions without adding your own type guards:

import { RecallSdk, isRecallSdkError } from '@coloop-ai/recall-sdk'

try {
  await recall.bot.create({
    meeting_url: 'https://zoom.us/j/123456789',
    bot_name: 'Demo bot',
  })
} catch (error) {
  if (!isRecallSdkError(error)) throw error

  if (error.status === 429) {
    // Surface rate limit metadata to tracing/logging before retrying.
    console.warn('Recall throttled request', error.payload)
    return
  }

  if (error.status === 400) {
    // Permanent failure — inspect error.detail/code for specifics.
    throw new Error(
      `Failed to create bot (${error.code ?? 'unknown'}): ${
        error.detail ?? error.message
      }`,
    )
  }
}

Idempotent requests

Methods that issue POST, PUT, or PATCH calls accept an optional IdempotentRequestOptions argument. Provide an idempotencyKey to send the Idempotency-Key header and safely retry requests as described in Recall's idempotency guide.

await recall.bot.create(
  {
    meeting_url: 'https://zoom.us/j/123456789',
    bot_name: 'Demo bot',
  },
  { idempotencyKey: 'my-idempotency-key' },
)

Request timeouts

Set timeoutMs when instantiating the SDK to automatically abort requests that exceed the configured duration. The SDK rejects with a RecallSdkTimeoutError, which you can treat as a retryable failure:

import { RecallSdk, RecallSdkTimeoutError } from '@coloop-ai/recall-sdk'

const recall = new RecallSdk({
  apiKey: process.env.RECALL_API_KEY!,
  timeoutMs: 5_000,
})

try {
  await recall.bot.list()
} catch (error) {
  if (error instanceof RecallSdkTimeoutError) {
    console.warn('Recall request timed out, retrying shortly')
    // retry or surface to your queue
  }
}

High-level methods

RecallSdk mirrors the most common Recall.ai workflows and groups operations into modules:

  • recall.bot – manage meeting bots (list, create, retrieve, update, delete, deleteMedia, leaveCall).
  • recall.calendar – convenience entry point with methods:
    • Calendar events: listEvents, retrieveEvent, scheduleBot, unscheduleBot.
    • Calendar accounts: listCalendars, createCalendar, retrieveCalendar, updateCalendar, deleteCalendar, createCalendarAccessToken.
    • Nested modules (recall.calendar.events and recall.calendar.accounts) expose the same methods if you prefer an explicit namespace.
  • recall.recording – work with meeting recordings (list, retrieve, delete, createTranscript).
  • recall.transcript – inspect transcript artifacts (list, retrieve, delete, update).
  • recall.audio – manage audio artifacts. Convenience helpers (listMixed, retrieveMixed, updateMixed, deleteMixed, listSeparate, retrieveSeparate, updateSeparate, deleteSeparate) delegate to nested modules (recall.audio.mixed, recall.audio.separate).
  • recall.video – manage video artifacts via the same helper pattern used for audio.

Every method takes lightweight identifiers (botId, eventId, calendarId, etc.) with optional request bodies or query objects that match the generated TypeScript types.

Paginated helpers (bots, calendars, calendar events, recordings, transcripts, audio/video artifacts) automatically replace the Recall-provided pagination URLs with the raw cursor tokens, so you can pass response.next or response.previous directly back via the cursor query param without any manual parsing.

Generated client access

If you need full control over request options (custom headers, alternative response styles, retries), you can work with the generated client directly:

import { GeneratedRecallSdk, sdk } from '@coloop-ai/recall-sdk'

const client = sdk.createClient({
  baseUrl: 'https://us-east-1.recall.ai',
  auth: () => `Token ${process.env.RECALL_API_KEY}`,
  responseStyle: 'body',
})

const raw = new GeneratedRecallSdk({ client })
const response = await raw.botList({ query: { status: ['ready'] } })

All request/response types are exported from @coloop-ai/recall-sdk, while webhook schemas live under @coloop-ai/recall-sdk/webhooks, so you can statically type your integrations even when using the low-level surface.

Webhooks

Recall's webhook payloads (bot lifecycle, Calendar v2 notifications, desktop upload lifecycle, etc.) are not included in the public OpenAPI definitions, so their schemas are hand-crafted in this SDK. The @coloop-ai/recall-sdk/webhooks entry point exports runtime validators and TypeScript types powered by Zod:

import {
  WebhookEvent,
  BotStatusCode,
  CallEndedSubCode,
} from '@coloop-ai/recall-sdk/webhooks'

export function handleWebhook(payload: unknown) {
  const parsed = WebhookEvent.safeParse(payload)
  if (!parsed.success) {
    console.warn('Unhandled webhook payload', parsed.error)
    return
  }

  const event = parsed.data
  switch (event.event) {
    case 'bot.status_change': {
      const { code, sub_code } = event.data.status
      if (code === BotStatusCode.enum.call_ended && sub_code) {
        const reason = CallEndedSubCode.safeParse(sub_code)
        if (reason.success) {
          console.log('Call ended with reason', reason.data)
        }
      }
      break
    }
    case 'calendar.sync_events': {
      const { calendar_id, last_updated_ts } = event.data
      console.log('Sync calendar', calendar_id, 'since', last_updated_ts)
      break
    }
  }
}

WebhookEvent doubles as the discriminated-union type (import type { WebhookEvent }) and the union validator (WebhookEvent.safeParse). Supporting enums such as BotStatusCode, CallEndedSubCode, FatalSubCode, ZoomRecordingPermissionDeniedSubCode, and others keep your matching logic aligned with Recall's surface, while the underlying payload fields still accept future string values so integrations keep compiling when Recall ships new codes.

Scripts

  • npm run generate – fetch merged specs and regenerate src/generated/**.
  • npm run tc – type-check the project without emitting files.
  • npm run lint – ESLint across the repository.
  • npm run test – Vitest suite (if meaningful behavior changed, add coverage).
  • npm run build – compile to dual ESM/CJS bundles in dist/ using tsdown (runs npm run generate first).

License

Released under the MIT License. See LICENSE for details.