Next.js API Routes (Route Handler): GET, POST, Auth | We.Inc
Kopierbare Next.js Route-Handler-Beispiele für den App Router: GET mit Query-Parametern, POST mit Validierung, dynamische params als Promise, Auth-Prüfungen, CORS und Webhooks.
Im App Router ist ein API-Endpunkt eine route.ts-Datei innerhalb von app, zum Beispiel app/api/todos/route.ts. Exportiere asynchrone Funktionen, die nach HTTP-Methoden wie GET und POST benannt sind; jede erhält einen Request und gibt eine Response zurück, meist Response.json(). Dynamische Segmente kommen als params-Promise an, das du mit await auflöst. GET-Handler sind seit Next.js 15 standardmäßig dynamisch.
Grundlagen von Route Handlern
Aufgabe
Code
JSON zurückgeben
return Response.json(data, { status: 200 })
JSON-Body lesen
const body = await request.json()
Formulardaten lesen
const form = await request.formData()
?q= lesen
request.nextUrl.searchParams.get("q")
Dynamisches Segment
const { id } = await params
Cookies / Header
await cookies(), await headers() from next/headers
API Routes im Pages Router nutzten req- und res-Objekte. Route Handler verwenden stattdessen die standardmäßigen Web-Objekte Request und Response, was jeden stolpern lässt, der ältere Antworten kopiert. Unten findest du die Muster, die du für eine echte App brauchst, jeweils für den aktuellen App Router geschrieben, plus einen kleinen Tester, der zeigt, welche Statuscodes ein validierender POST zurückgeben sollte.
Fülle im Tester den simulierten Request-Body aus und wähle, ob der Aufrufer angemeldet ist.
Der Tester wendet in deinem Browser dieselben Validierungsregeln an wie das POST-Beispiel auf dieser Seite.
Lies den zurückgegebenen Statuscode und das JSON, und ändere dann ein Feld, um einen 400, 401 oder 201 zu sehen.
Kopiere den Beispiel-Handler und ersetze die Liste im Arbeitsspeicher durch deine Datenbank.
Behandle jeden Handler als öffentlichen Endpunkt. Prüfe die Session im Handler, auch wenn proxy abgemeldete Nutzer bereits umgeleitet hat.
Validiere den Body mit einer Schema-Bibliothek wie Zod und sende 400 mit Feldfehlern, statt eine fehlerhafte Payload einen 500 auslösen zu lassen.
Eine route.ts-Datei kann nicht im selben Ordner wie eine page.tsx liegen; lege APIs unter app/api ab, um sie getrennt zu halten.
Wenn du OPTIONS nicht exportierst, beantwortet Next.js die Anfrage für dich mit einem Allow-Header, der die exportierten Methoden auflistet.
Lies bei Webhooks den rohen Body mit request.text() vor dem Parsen, denn Signaturprüfungen brauchen die exakten Bytes.
Häufige Fragen
Sind Next.js API Routes veraltet?
pages/api-Routen funktionieren im Pages Router weiterhin. Im App Router ist das Gegenstück ein Route Handler, eine route.ts-Datei, die Web-Objekte Request und Response nutzt und keine bodyParser-Konfiguration braucht.
Welche HTTP-Methoden kann eine route.ts exportieren?
GET, POST, PUT, PATCH, DELETE, HEAD und OPTIONS. Der Aufruf einer nicht exportierten Methode gibt 405 Method Not Allowed zurück.
Warum muss ich params mit await auflösen?
Seit Next.js 15 ist params im context-Argument ein Promise. Schreib const { id } = await params. Der Hilfstyp RouteContext, erzeugt von next dev, next build oder next typegen, liefert dir typisierte params aus dem Routenpfad.
Werden GET Route Handler gecacht?
Standardmäßig nicht mehr. Next.js 15 hat GET-Handler von statisch auf dynamisch umgestellt. Caching aktivierst du wieder mit export const dynamic = 'force-static' oder einem revalidate-Wert. Mit aktivierten Cache Components setzt du use cache in eine Hilfsfunktion, die der Handler aufruft, nicht in den Handler selbst.
Sollte ich einen Route Handler oder eine Server Action verwenden?
Nutze eine Server Action für Änderungen, die von deinen eigenen Formularen und Buttons ausgelöst werden. Nutze einen Route Handler, wenn etwas außerhalb deines React-Baums die URL aufruft: eine mobile App, ein Webhook, ein Cronjob oder ein Skript von Drittanbietern.
Dateistruktur
Der Ordnerpfad ist die URL. app/api/todos/route.ts beantwortet /api/todos, und app/api/todos/[id]/route.ts beantwortet /api/todos/42. Ein Catch-all-Ordner wie [...slug] übergibt ein Array von Segmenten.
Route Handler teilen sich die Segment-Konfiguration mit Seiten, daher gelten für sie dieselben Exporte dynamic, revalidate und runtime.
Statuscodes, die Clients verstehen
Sende 201 nach dem Erstellen von etwas, 400 bei falscher Eingabe, 401 wenn niemand angemeldet ist, 403 wenn dem angemeldeten Nutzer die Berechtigung fehlt, 404 wenn der Datensatz nicht existiert und 405 für nicht unterstützte Methoden. Frontends können dann anhand des Codes verzweigen, statt Fehlertext zu parsen.
Gib für Fehler eine einheitliche JSON-Struktur zurück, etwa { error: string, fields?: object }, damit ein einziger fetch-Helfer alle verarbeiten kann.
Sicherheits-Checkliste
Prüfe die Session, stelle sicher, dass der Nutzer den Datensatz besitzt, den er ändert, validiere die Payload und gib niemals Geheimnisse oder komplette Nutzerzeilen zurück. Der offizielle Authentifizierungsleitfaden zeigt dieses zweistufige Muster mit 401 für fehlende Session und 403 für die falsche Rolle.
Setze CORS-Header nur bei Handlern, die andere Origins wirklich aufrufen müssen, und nenne konkrete Origins statt eines Sternchens, sobald Cookies im Spiel sind.
Beispiele für Route Handler
GET mit einer Suchanfrage
app/api/todos/route.ts. Der Parameter q filtert die Liste; eine leere Anfrage gibt alles zurück.
POST mit Zod-Validierung und Auth-Prüfung
Gibt ohne Session 401 zurück, bei fehlerhaftem Body 400 mit Feldfehlern und sonst 201 mit dem neuen Datensatz. getSession steht stellvertretend für deine Auth-Bibliothek.
Dynamisches Segment mit params per await
app/api/todos/[id]/route.ts. params ist ab Next.js 15 ein Promise.
CORS für eine vertrauenswürdige Origin
Beantwortet den Preflight des Browsers und die eigentliche Anfrage mit derselben erlaubten Origin.
Den Handler aus einer Client Component aufrufen
Der fetch-Helfer liest zuerst den Statuscode, damit das Formular Feldfehler aus einem 400 anzeigen kann.
API Routes im Pages Router vs. Route Handler
Gleiche Aufgabe, unterschiedliche APIs
pages/api/x.ts
app/api/x/route.ts
Handler
export default function handler(req, res)
export async function GET(request)
JSON senden
res.status(200).json(data)
return Response.json(data)
Methodenweiche
if (req.method === "POST")
eine separat exportierte POST-Funktion
Body-Parsing
req.body (bodyParser-Konfiguration)
await request.json() oder request.formData()
Query-String
request.nextUrl.searchParams
POST-Tester
Bearbeite einen JSON-Body, wähle, ob der Aufrufer angemeldet ist, und sieh den Statuscode und die Antwort, die das validierende POST-Beispiel zurückgeben würde.
Methode
Request-Body (JSON)
Aufrufer hat eine gültige Session
Antwort
PUT zeigt den 405, den Next.js für eine Methode sendet, die die Datei nicht exportiert.