← Integrations
Email
Seshn + Resend
Send booking confirmations, cancellation notices, and reminders using Resend and Seshn webhooks.
Install
1npm install resendWebhook events
Register a Seshn webhook for the events you want to send emails for. The most common:
booking.createdSend a confirmation emailbooking.confirmedNotify after payment completesbooking.cancelledSend a cancellation noticebooking.rescheduledNotify of new date/timewaitlist.promotedLet them know they got a spotWebhook handler
A Next.js API route that receives Seshn webhooks and sends emails via Resend.
app/api/webhooks/seshn/route.ts
1import { Resend } from 'resend';2import { createHmac } from 'crypto';34const resend = new Resend(process.env.RESEND_API_KEY);5const WEBHOOK_SECRET = process.env.SESHN_WEBHOOK_SECRET!;67export async function POST(req: Request) {8 const body = await req.text();9 const signature = req.headers.get('x-webhook-signature');1011 // Verify the webhook signature12 const expected = 'sha256=' +13 createHmac('sha256', WEBHOOK_SECRET).update(body).digest('hex');1415 if (signature !== expected) {16 return new Response('Invalid signature', { status: 401 });17 }1819 const event = req.headers.get('x-webhook-event');20 const payload = JSON.parse(body);2122 switch (event) {23 case 'booking.created':24 await resend.emails.send({25 from: 'bookings@yourdomain.com',26 to: payload.contact.email,27 subject: 'Booking confirmed',28 html: `29 <h1>You're booked!</h1>30 <p><strong>${payload.service.name}</strong></p>31 <p>${new Date(payload.slot.startTime).toLocaleString()}</p>32 <p>${payload.seats} seat(s) reserved.</p>33 `,34 });35 break;3637 case 'booking.cancelled':38 await resend.emails.send({39 from: 'bookings@yourdomain.com',40 to: payload.contact.email,41 subject: 'Booking cancelled',42 html: `43 <h1>Booking cancelled</h1>44 <p>Your booking for <strong>${payload.service.name}</strong> has been cancelled.</p>45 `,46 });47 break;4849 case 'booking.rescheduled':50 await resend.emails.send({51 from: 'bookings@yourdomain.com',52 to: payload.contact.email,53 subject: 'Booking rescheduled',54 html: `55 <h1>New time confirmed</h1>56 <p><strong>${payload.service.name}</strong></p>57 <p>${new Date(payload.newSlot.startTime).toLocaleString()}</p>58 `,59 });60 break;6162 case 'waitlist.promoted':63 await resend.emails.send({64 from: 'bookings@yourdomain.com',65 to: payload.contact.email,66 subject: 'You got a spot!',67 html: `68 <h1>Good news!</h1>69 <p>A spot opened up for <strong>${payload.service.name}</strong>70 and you've been automatically booked.</p>71 `,72 });73 break;74 }7576 return new Response('OK', { status: 200 });77}Register the webhook
terminal
1curl -X POST https://api.seshn.net/v1/webhooks \2 -H "Authorization: Bearer sk_live_..." \3 -H "Content-Type: application/json" \4 -d '{5 "url": "https://yourdomain.com/api/webhooks/seshn",6 "events": [7 "booking.created",8 "booking.confirmed",9 "booking.cancelled",10 "booking.rescheduled",11 "waitlist.promoted"12 ]13 }'Next steps
- Use React Email for beautiful, type-safe templates.
- Add a
booking.hold_expiredhandler to notify customers their hold timed out. - Use the
x-webhook-idheader as an idempotency key for Resend.