Integration
Send emails from SvelteKit with Postkit
Send transactional emails from SvelteKit server endpoints and form actions. Works with any adapter.
1. Set your API key
# .env POSTKIT_API_KEY=pk_live_...
2. Send an email
typescript
// src/routes/api/send/+server.ts
import { POSTKIT_API_KEY } from "$env/static/private";
import { json } from "@sveltejs/kit";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request }) => {
const { to, name } = await request.json();
const res = await fetch("https://api.postkit.eu/v1/emails", {
method: "POST",
headers: {
Authorization: `Bearer ${POSTKIT_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
from: "hello@yourapp.eu",
to,
subject: "Welcome aboard!",
html: `<h1>Welcome, ${name}!</h1>`,
}),
});
return json(await res.json());
};3. Handle webhooks
Postkit sends delivery events (sent, delivered, bounced, opened, clicked) via HMAC-SHA256 signed webhooks following the Standard Webhooks specification.
typescript
// src/routes/webhooks/postkit/+server.ts
import { POSTKIT_WEBHOOK_SECRET } from "$env/static/private";
import { json, error } from "@sveltejs/kit";
import crypto from "crypto";
import type { RequestHandler } from "./$types";
export const POST: RequestHandler = async ({ request }) => {
const body = await request.text();
const msgId = request.headers.get("webhook-id") ?? "";
const timestamp = request.headers.get("webhook-timestamp") ?? "";
const signature = request.headers.get("webhook-signature") ?? "";
const secret = Buffer.from(
POSTKIT_WEBHOOK_SECRET.replace("whsec_", ""),
"base64"
);
const content = `${msgId}.${timestamp}.${body}`;
const expected = crypto
.createHmac("sha256", secret)
.update(content)
.digest("base64");
const valid = signature.split(" ").some((sig) => {
const val = sig.replace(/^v1,/, "");
return crypto.timingSafeEqual(
Buffer.from(val, "base64"),
Buffer.from(expected, "base64")
);
});
if (!valid) throw error(401, "Invalid signature");
const event = JSON.parse(body);
console.log("Postkit event:", event.type);
return json({ received: true });
};