jasni-sdk
v0.5.1
Published
Official TypeScript SDK for the Jasni Email API
Maintainers
Readme
Jasni SDK
Official TypeScript/JavaScript SDK for the Jasni Email API.
Installation
npm install jasni-sdkQuick 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 receivedemail.sent- Email sentemail.bounced- Email bouncedemail.spam- Email marked as spamemail.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
