Crash Courses · PhD
Webhooks & Event-Driven APIs
Implement webhooks to push real-time events and verify signature security.
10 min read+200 XP on completionCert: REST APIs Crash Course
Tap any word in the text below to start reading from there.
Webhooks & Event-Driven APIs
Webhooks let third-party services notify you of events in real time. You build the receiver; they call it.
Webhook Receiver with Signature Verification
// app/api/webhooks/stripe/route.ts
import { NextRequest, NextResponse } from 'next/server'
import crypto from 'crypto'
function verifySignature(
payload: string,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex')
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
)
}
export async function POST(req: NextRequest) {
// Get raw body BEFORE parsing JSON
const rawBody = await req.text()
const signature = req.headers.get('x-stripe-signature') ?? ''
if (!verifySignature(rawBody, signature, process.env.STRIPE_WEBHOOK_SECRET!)) {
return NextResponse.json({ error: 'Invalid signature' }, { status: 401 })
}
const event = JSON.parse(rawBody)
const idempotencyKey = event.id
// Check for duplicate event
const already = await db.processedEvents.findUnique({ where: { id: idempotencyKey } })
if (already) return NextResponse.json({ received: true })
// Process event
switch (event.type) {
case 'payment_intent.succeeded':
await handlePayment(event.data.object)
break
}
// Mark as processed
await db.processedEvents.create({ data: { id: idempotencyKey } })
return NextResponse.json({ received: true })
}
// Disable body parsing (Next.js default) — we need raw text
export const config = { api: { bodyParser: false } }Sending Webhooks (Outbound)
async function sendWebhook(url: string, event: object, secret: string) {
const payload = JSON.stringify(event)
const signature = crypto.createHmac('sha256', secret).update(payload).digest('hex')
await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Webhook-Signature': signature,
},
body: payload,
})
}Reading progress
0% read
In this module
Webhook
HMAC signature
Idempotency key
Retry logic
0%