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

@ear3/server

v0.1.8

Published

Server SDK for Ear3 — webhook verification (HMAC), session mint and retrieval.

Downloads

1,026

Readme

@ear3/server

🤖 AI agents / LLMs: start with AGENTS.md, then llms.txt — both bundled in this package (also at https://www.ear3.ai/llms.txt). They are the complete machine-readable guide: commands, ids, and the exact create → deploy → integrate flow. To make Claude Code pick this up automatically in your project, add one line to your CLAUDE.md:

@node_modules/@ear3/server/AGENTS.md

Server SDK for Ear3. Use this on your backend to create sessions programmatically, fetch results, and verify inbound webhook signatures. Runs on Node 18+ (native fetch + node:crypto).

For browser-side embedding, use @ear3/voice-interviewer instead.

Need an interviewId? The fastest, recommended way to create one is the CLI — sign in once with npx @ear3/voice-config-cli login, then npx @ear3/voice-config-cli create --name "…" --prompt "…" generates and deploys an AI interview in a single command and prints the interviewId (npx @ear3/voice-config-cli list shows existing ones). Or create it in the dashboard.

Install

npm install @ear3/server

Quick start

import { Ear3 } from '@ear3/server'

const ear3 = new Ear3(process.env.EAR3_CONFIG_CLI_KEY!) // sk_live_… or sk_test_…

// Create a session and email it to a respondent
const session = await ear3.sessions.create({
  interviewId: 'dpl_a1b2c3d4',
  participantName: 'Olena K.', // dashboard display name (optional)
  participantExternalId: 'crm_42', // your own respondent id (optional)
  metadata: { userId: '123', source: 'march-campaign' },
})

await sendEmail({
  to: user.email,
  subject: 'Quick interview',
  body: `Tap here when you have 5 minutes: ${session.sessionUrl}`,
})

Retrieve a completed session

const session = await ear3.sessions.retrieve('inv_…')

if (session.status === 'COMPLETED' && session.response) {
  console.log('Transcript:', session.response.transcriptKey)
  console.log('Summary:', session.response.summary)
}

Verify webhooks

Ear3 posts events (interview.completed, interview.failed, …) to your webhook endpoint. Always verify the signature before trusting the payload.

import express from 'express'
import { Ear3, SignatureVerificationError } from '@ear3/server'

const ear3 = new Ear3(process.env.EAR3_CONFIG_CLI_KEY!)
const app = express()

// IMPORTANT: read raw body — JSON parsing changes whitespace and breaks the
// signature.
app.post('/webhooks/ear3', express.raw({ type: 'application/json' }), (req, res) => {
  try {
    const event = ear3.webhooks.constructEvent(
      req.body.toString('utf8'),
      req.headers['ear3-signature'] as string,
      process.env.EAR3_WEBHOOK_SECRET!,
    )

    if (event.type === 'interview.completed') {
      // event.data is typed if you pass a generic: constructEvent<MyType>(…)
      handleCompletion(event.data)
    }

    res.json({ received: true })
  } catch (err) {
    if (err instanceof SignatureVerificationError) {
      return res.status(400).send('Invalid signature')
    }
    throw err
  }
})

Next.js App Router

// app/api/webhooks/ear3/route.ts
import { Ear3, SignatureVerificationError } from '@ear3/server'

const ear3 = new Ear3(process.env.EAR3_CONFIG_CLI_KEY!)

export async function POST(req: Request) {
  const rawBody = await req.text() // raw, before any JSON.parse
  const signature = req.headers.get('ear3-signature') ?? ''

  try {
    const event = ear3.webhooks.constructEvent(
      rawBody,
      signature,
      process.env.EAR3_WEBHOOK_SECRET!,
    )

    if (event.type === 'interview.completed') {
      await handleCompletion(event.data)
    }

    return Response.json({ received: true })
  } catch (err) {
    if (err instanceof SignatureVerificationError) {
      return new Response('Invalid signature', { status: 400 })
    }
    throw err
  }
}

Constructor options

new Ear3(secretKey, {
  baseUrl?: string         // default https://app.ear3.ai
  fetchOptions?: RequestInit // applied to every request
})

Self-hosting / dev

const ear3 = new Ear3('sk_test_…', { baseUrl: 'http://localhost:3000' })

Or set EAR3_BASE_URL once in your env and the SDK picks it up:

EAR3_BASE_URL=http://localhost:3000

Resolution order: explicit baseUrl option > EAR3_BASE_URL env > default (https://app.ear3.ai).

Errors

  • Ear3Error — HTTP failures from the API (.status, .code, .message)
  • SignatureVerificationError — webhook signature mismatch, malformed header, expired timestamp (default tolerance 5 min)

Claude Code plugin

Using Claude Code? The Ear3 plugin's /ear3:create-interview skill takes you from a plain-language topic to a deployed interview (and the interviewId + key this package needs) in one go — Claude also invokes it on its own when you ask to create an interview:

/plugin marketplace add https://www.ear3.ai/claude/marketplace.json
/plugin install ear3@ear3

Not using Claude Code plugins? (Cursor, Codex, plain agents): copy skills/create-interview/ into your project's .claude/skills/ — it works without the namespace, as /create-interview.

License

MIT