Skip to main content
Juliano Alves
Back to blog

Route Handlers in Next.js for webhooks and APIs

3 min read
By Juliano Alves

app/api/**/route.ts (or route.js) defines Route Handlers: HTTP methods as named exports (GET, POST) colocated with the App Router. They replace much of what you previously did in pages/api but follow Web Request/Response APIs.

Stripe-style webhook#

import { headers } from 'next/headers';
import Stripe from 'stripe';

export async function POST(req: Request) {
  const body = await req.text();
  const sig = headers().get('stripe-signature');
  if (!sig) return new Response('Missing signature', { status: 400 });

  let event: Stripe.Event;
  try {
    event = stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!);
  } catch {
    return new Response('Invalid signature', { status: 400 });
  }

  // Idempotent: store event.id before side effects
  await processStripeEvent(event);
  return new Response(null, { status: 200 });
}

Use req.text() not req.json() when the provider signs the raw body.

Dynamic routes#

app/api/users/[id]/route.ts exports handlers with context.params. Validate id before DB calls.

Edge vs Node#

Pick export const runtime = 'edge' only when dependencies support it (no Node-only Stripe SDK on edge without wasm). Webhooks often need Node for crypto and official SDKs.

Summary#

Route Handlers are ideal for webhooks and small BFF endpoints. Verify signatures on raw bodies, run idempotent business logic, and choose runtime based on library support—not hype.

© 2026 Juliano Alves. All rights reserved.