Webhook Verification
Verify that incoming OpenSES webhook payloads are authentic.
OpenSES signs the raw request body with HMAC-SHA256 and sends the result in X-OpenSES-Signature.
Next.js App Router
import { verifyWebhook } from '@openses/openses';
export async function POST(request: Request) {
const rawBody = await request.text();
const signature = request.headers.get('x-openses-signature') ?? '';
const { data } = verifyWebhook({
payload: rawBody,
signature,
secret: process.env.OPENSES_WEBHOOK_SECRET!,
});
console.log(data.type);
console.log(data.data.email_id);
return new Response(null, { status: 200 });
}Express
import express from 'express';
import { verifyWebhook } from '@openses/openses';
const app = express();
app.post(
'/webhooks/openses',
express.raw({ type: 'application/json' }),
(request, response) => {
const { data } = verifyWebhook({
payload: request.body.toString('utf8'),
signature: request.header('x-openses-signature') ?? '',
secret: process.env.OPENSES_WEBHOOK_SECRET!,
});
console.log(data.type);
response.sendStatus(200);
}
);Do not call express.json() before verification on this route. Parsing and re-serializing JSON changes the signed bytes.
Payload shape
type WebhookPayload = {
type: `email.${string}`;
created_at: string;
data: {
email_id: string;
from: string;
to: string[];
subject: string;
status: string;
event: {
type: string;
created_at: string;
metadata?: Record<string, unknown>;
};
};
};