Webhook examples
Next.js webhook example
Receive and verify Yanola webhook events in a server-side Next.js route handler.
DevelopersAdvancedAvailable
What this guide covers
- Read the request body as text or bytes before parsing JSON.
- Keep the webhook signing secret in server-only environment configuration.
- Return a prompt 2xx response after safely accepting the event.
Create a server-only Route Handler
Place the handler in the App Router and keep YANOLA_WEBHOOK_SECRET in server-only deployment configuration. Route Handlers use the standard Request API; read the body as text exactly once.
dotenv
YANOLA_WEBHOOK_SECRET=your_copy_once_endpoint_secretComplete Next.js App Router route
ts
import {
verifyYanolaWebhookSignature,
} from "@yanola/whatsapp"
export const runtime = "nodejs"
export async function POST(request: Request): Promise<Response> {
const signingSecret = process.env.YANOLA_WEBHOOK_SECRET
if (!signingSecret) {
return Response.json(
{ error: "Webhook signing secret is not configured" },
{ status: 500 }
)
}
const rawBody = await request.text()
const valid = verifyYanolaWebhookSignature({
secret: signingSecret,
signature: request.headers.get("yanola-signature"),
rawBody,
})
if (!valid) {
return Response.json(
{ error: "Invalid Yanola signature" },
{ status: 400 }
)
}
const event = JSON.parse(rawBody)
await acceptEventOnce(event)
return new Response(null, { status: 204 })
}Do not call request.json first
A Request body is a one-use stream. request.text() preserves the received text for verification; parse that same string only after the signature is valid.
Keep the Node.js runtime
The Node.js runtime is the default for Route Handlers and is declared explicitly here because the SDK verifier uses Node's crypto implementation. Do not move this handler into a client component or expose the secret through NEXT_PUBLIC_ configuration.
Persist once, process later
- Use event.id as a unique key in your database or durable queue.
- Write the event and enqueue future work atomically where possible.
- Treat a duplicate ID as successful durable acceptance.
- Return 204 within Yanola's 10-second timeout.
- Run slow calls from a background worker.
Configure Yanola
- Deploy the route and confirm the public URL ends at /api/webhooks/yanola.
- Create a matching endpoint in the Agent Project dashboard.
- Use a Test endpoint and secret first.
- Select the payload mode your runtime validator expects.
- Send a dashboard test event and inspect its delivery record.
Common Next.js mistakes
| Mistake | Correction |
|---|---|
Calling request.json() before verification | Call request.text() once, verify, then JSON.parse(rawBody). |
Using NEXT_PUBLIC_YANOLA_WEBHOOK_SECRET | Use a server-only environment variable. |
Returning before durable persistence | Await the database or durable queue acceptance. |
Parsing as a typed object without validation | Validate untrusted JSON after signature verification. |