Skip to main content
The webhooks resource allows you to create, list, update, and delete webhooks for receiving real-time notifications about email events.

List Webhooks

Retrieve all webhooks:
const { webhooks } = await jasni.webhooks.list()

webhooks.forEach(webhook => {
  console.log(`${webhook.url} - Events: ${webhook.events.join(', ')}`)
  console.log(`  Active: ${webhook.active}`)
})

Response

interface Webhook {
  id: string
  url: string
  events: WebhookEvent[]
  active: boolean
  description?: string
  created_at: string
  updated_at?: string
}

interface ListWebhooksResponse {
  webhooks: Webhook[]
}

Create Webhook

Create a new webhook:
const { webhook } = await jasni.webhooks.create({
  url: 'https://my-server.com/webhook',
  events: ['email.received', 'email.sent'],
  description: 'My webhook',  // Optional
})

// IMPORTANT: Save the secret! It's only returned on creation
console.log('Webhook ID:', webhook.id)
console.log('Webhook Secret:', webhook.secret)
Save your webhook secret! The secret is only returned when the webhook is created. You’ll need it to verify incoming webhook payloads.

Options

ParameterTypeRequiredDescription
urlstringYesWebhook URL (must be HTTP or HTTPS)
eventsWebhookEvent[]YesEvents to subscribe to
descriptionstringNoDescription

Available Events

EventDescription
email.receivedNew email received
email.sentEmail sent
email.bouncedEmail bounced
email.spamEmail marked as spam
email.deletedEmail deleted

Response

interface CreateWebhookResponse {
  webhook: Webhook & { secret: string }
}

Update Webhook

Update an existing 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
})

Options

ParameterTypeRequiredDescription
idstringYesWebhook ID
urlstringNoNew URL
eventsWebhookEvent[]NoEvents to subscribe to
activebooleanNoEnable/disable webhook
descriptionstringNoDescription

Response

interface UpdateWebhookResponse {
  webhook: Webhook
}

Delete Webhook

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

Example: Webhook Management

Here’s a complete example of managing webhooks:
import { Jasni } from 'jasni-sdk'

const jasni = new Jasni('jsk_your_api_key')

async function manageWebhooks() {
  // Create a webhook for all email events
  const { webhook } = await jasni.webhooks.create({
    url: 'https://my-server.com/jasni-webhook',
    events: ['email.received', 'email.sent', 'email.bounced'],
    description: 'Production webhook',
  })
  
  console.log('Created webhook:', webhook.id)
  console.log('Secret (save this!):', webhook.secret)
  
  // List all webhooks
  const { webhooks } = await jasni.webhooks.list()
  console.log(`Total webhooks: ${webhooks.length}`)
  
  // Disable a webhook temporarily
  await jasni.webhooks.update({
    id: webhook.id,
    active: false,
  })
  console.log('Webhook disabled')
  
  // Re-enable and update events
  await jasni.webhooks.update({
    id: webhook.id,
    active: true,
    events: ['email.received'],  // Only receive events
  })
  console.log('Webhook enabled with updated events')
  
  // Delete a webhook
  await jasni.webhooks.delete(webhook.id)
  console.log('Webhook deleted')
}

manageWebhooks().catch(console.error)

Verifying Webhook Signatures

When receiving webhook payloads, verify the signature to ensure they’re from Jasni:
import crypto from 'crypto'

function verifyWebhookSignature(
  payload: string,
  signature: string,
  secret: string
): boolean {
  const expectedSignature = crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex')
  
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expectedSignature)
  )
}

// In your webhook handler (Express example)
app.post('/jasni-webhook', (req, res) => {
  const signature = req.headers['x-jasni-signature'] as string
  const payload = JSON.stringify(req.body)
  
  if (!verifyWebhookSignature(payload, signature, process.env.JASNI_WEBHOOK_SECRET!)) {
    return res.status(401).send('Invalid signature')
  }
  
  // Process the webhook
  const event = req.body
  console.log('Received event:', event.type)
  
  switch (event.type) {
    case 'email.received':
      console.log('New email from:', event.data.from)
      break
    case 'email.sent':
      console.log('Email sent to:', event.data.to)
      break
    case 'email.bounced':
      console.log('Email bounced:', event.data.bounce_reason)
      break
  }
  
  res.status(200).send('OK')
})

Webhook Payload Structure

All webhook payloads follow this structure:
interface WebhookPayload {
  id: string           // Unique event ID
  type: WebhookEvent   // Event type
  created_at: string   // ISO timestamp
  data: {
    account: string    // Email account
    uid: number        // Email UID
    message_id: string // Message ID
    from: string       // Sender
    to: string[]       // Recipients
    subject: string    // Subject
    // Additional fields based on event type
  }
}
For more details on webhook payloads and best practices, see the Webhooks Guide.