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

jasni-sdk

v0.5.1

Published

Official TypeScript SDK for the Jasni Email API

Readme

Jasni SDK

Official TypeScript/JavaScript SDK for the Jasni Email API.

Installation

npm install jasni-sdk

Quick Start

import { Jasni } from 'jasni-sdk'

const jasni = new Jasni('jsk_your_api_key')

// List accounts
const { accounts } = await jasni.accounts.list()
console.log(accounts)

// Send an email
const result = await jasni.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Hello from Jasni!',
  text: 'This email was sent using the Jasni SDK.',
})
console.log('Sent:', result.messageId)

Configuration

const jasni = new Jasni('jsk_your_api_key', {
  baseUrl: 'https://api.jasni.ai', // Optional: custom base URL
})

API Reference

Accounts

// List all email accounts
const { accounts } = await jasni.accounts.list()

// Create a new email account
const { account } = await jasni.accounts.create({
  username: 'myaccount',  // Optional: auto-generated if not provided
  name: 'My Account',     // Optional: display name
})

// Update an account
await jasni.accounts.update({
  email: '[email protected]',
  name: 'New Display Name',
})

// Delete an email account
await jasni.accounts.delete('[email protected]')

Emails

// List emails
const { emails } = await jasni.emails.list({
  account: '[email protected]',
  folder: 'INBOX',  // Optional: default is INBOX
  limit: 50,        // Optional: default is 50, max 100
})

// Get a specific email
const { email } = await jasni.emails.get(123, {
  account: '[email protected]',
  folder: 'INBOX',
})

// Delete an email
await jasni.emails.delete(123, {
  account: '[email protected]',
})

// Mark as read/unread
await jasni.emails.markAsRead(123, { account: '[email protected]' })
await jasni.emails.markAsUnread(123, { account: '[email protected]' })

// Send an email
const result = await jasni.emails.send({
  from: '[email protected]',
  to: ['[email protected]'],
  subject: 'Hello!',
  text: 'Plain text body',
  html: '<p>HTML body</p>',  // Optional
  cc: ['[email protected]'],    // Optional
  bcc: ['[email protected]'],  // Optional
  replyTo: '[email protected]', // Optional
})

// Reply to an email
const reply = await jasni.emails.reply(123, {
  account: '[email protected]',
  text: 'Thanks for your email!',
  replyAll: false,         // Optional: default false
  includeOriginal: true,   // Optional: default true
})

// Forward an email
const forward = await jasni.emails.forward(123, {
  account: '[email protected]',
  to: ['[email protected]'],
  text: 'FYI - see below',  // Optional message
})

// Get all attachments from an email
const { attachments } = await jasni.emails.getAttachments(123, {
  account: '[email protected]',
})
for (const att of attachments) {
  console.log(att.filename, att.contentType, att.size)
  // att.content is base64 encoded
}

// Get a specific attachment (by filename or index)
const { attachment } = await jasni.emails.getAttachment(123, {
  account: '[email protected]',
  attachment: 'document.pdf',  // or use index: 0
})

// Get raw email (RFC 822 format)
const { raw } = await jasni.emails.getRaw(123, {
  account: '[email protected]',
})

// Filter emails by labels
const { emails } = await jasni.emails.list({
  account: '[email protected]',
  labels: ['Important', 'Work'],  // Filter by label names
  // OR
  labelIds: ['label-id-1', 'label-id-2'],  // Filter by label IDs
})

Threads (Conversations)

// List email threads
const { threads, totalThreads } = await jasni.emails.listThreads({
  account: '[email protected]',
  folder: 'INBOX',  // Optional
  limit: 100,       // Optional
})

for (const thread of threads) {
  console.log(`${thread.subject} (${thread.messageCount} messages)`)
}

// Get all emails in a thread
const thread = await jasni.emails.getThread('<[email protected]>', {
  account: '[email protected]',
})

console.log(`Thread: ${thread.subject}`)
console.log(`Participants: ${thread.participants.map(p => p.address).join(', ')}`)

for (const email of thread.emails) {
  console.log(`- ${email.from.address}: ${email.text}`)
}

Drafts

// List drafts
const { drafts } = await jasni.drafts.list({
  account: '[email protected]',
  limit: 50,
})

// Create a draft
const { uid } = await jasni.drafts.create({
  account: '[email protected]',
  to: '[email protected]',
  subject: 'Draft subject',
  text: 'Draft body',
})

// Update a draft
await jasni.drafts.update({
  account: '[email protected]',
  uid: 123,
  subject: 'Updated subject',
  text: 'Updated body',
})

// Delete a draft
await jasni.drafts.delete({
  account: '[email protected]',
  uid: 123,
})

// Get a specific draft
const { email } = await jasni.drafts.get(123, {
  account: '[email protected]',
})

// Send a draft (removes it from Drafts folder)
const result = await jasni.drafts.send({
  account: '[email protected]',
  uid: 123,
})
console.log('Sent with message ID:', result.messageId)

Labels

// List labels
const { labels } = await jasni.labels.list({
  includeCount: true,  // Optional: include email count per label
})

// Create a label
const { label } = await jasni.labels.create({
  name: 'Important',
  color: '#ff0000',      // Optional: hex color
  description: 'Important emails',  // Optional
})

// Delete a label
await jasni.labels.delete('label-id')

// Get labels for an email
const { labels } = await jasni.emails.labels.list(123, {
  account: '[email protected]',
})

// Assign labels to an email
await jasni.emails.labels.assign(123, {
  account: '[email protected]',
  labels: ['Important', 'Work'],     // Create labels if they don't exist
  // OR
  labelIds: ['label-id-1', 'label-id-2'],  // Use existing label IDs
  agentName: 'my-agent',  // Optional: for tracking
  metadata: { reason: 'Auto-categorized' },  // Optional
})

// Remove labels from an email
await jasni.emails.labels.remove(123, {
  account: '[email protected]',
  labelIds: ['label-id-1'],
})

Webhooks

// List webhooks
const { webhooks } = await jasni.webhooks.list()

// Get a specific webhook by ID
const { webhook } = await jasni.webhooks.get('webhook-id')
console.log(webhook.url, webhook.events, webhook.active)

// Create a webhook
const { webhook } = await jasni.webhooks.create({
  url: 'https://my-server.com/webhook',
  events: ['email.received', 'email.sent'],
  description: 'My webhook',  // Optional
})
// Note: The secret is only returned on creation

// Update a webhook
await jasni.webhooks.update({
  id: 'webhook-id',
  url: 'https://new-url.com/webhook',  // Optional
  events: ['email.received'],           // Optional
  active: false,                         // Optional
  description: 'Updated description',    // Optional
})

// Delete a webhook
await jasni.webhooks.delete('webhook-id')

Webhook Events

  • email.received - New email received
  • email.sent - Email sent
  • email.bounced - Email bounced
  • email.spam - Email marked as spam
  • email.deleted - Email deleted

Verifying Webhook Signatures

Jasni signs all webhook payloads with HMAC-SHA256. Use the provided utilities to verify signatures:

import { verifySignature, constructEvent } from 'jasni-sdk'

// Express.js example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const payload = req.body
  const signature = req.headers['x-jasni-signature'] as string

  // Option 1: Manual verification
  if (verifySignature(payload, signature, webhookSecret)) {
    const event = JSON.parse(payload.toString())
    handleEvent(event)
  } else {
    return res.status(401).send('Invalid signature')
  }

  // Option 2: Using constructEvent (verifies and parses)
  try {
    const event = constructEvent(payload, signature, webhookSecret)
    
    if (event.event === 'email.received') {
      console.log('New email from:', event.data.from)
    }
    
    res.status(200).send('OK')
  } catch (err) {
    res.status(401).send('Invalid signature')
  }
})

For testing, you can generate signatures:

import { generateSignature } from 'jasni-sdk'

const payload = JSON.stringify({ event: 'email.received', data: {} })
const signature = generateSignature(payload, 'whsec_test_secret')

Error Handling

import { Jasni, JasniError, AuthenticationError, NotFoundError } from 'jasni-sdk'

try {
  await jasni.emails.get(999, { account: '[email protected]' })
} catch (error) {
  if (error instanceof AuthenticationError) {
    console.error('Invalid API key')
  } else if (error instanceof NotFoundError) {
    console.error('Email not found')
  } else if (error instanceof JasniError) {
    console.error(`API error: ${error.message} (${error.status})`)
  }
}

TypeScript Support

This SDK is written in TypeScript and includes full type definitions.

import type { 
  // Core types
  Email, 
  EmailPreview,
  EmailAddress,
  Account, 
  Label, 
  Webhook,
  Draft,
  ThreadPreview,
  
  // Options types
  SendEmailOptions,
  ListEmailsOptions,
  ListThreadsOptions,
  CreateDraftOptions,
  CreateWebhookOptions,
  
  // Webhook payload types
  WebhookPayload,
  EmailReceivedPayload,
  EmailSentPayload,
} from 'jasni-sdk'

License

MIT