REST APIs sind das Rückgrat moderner Softwareentwicklung. Ob Mobile-App, Single-Page-Application oder Microservice-Architektur – fast jede Anwendung kommuniziert über REST-Schnittstellen. In dieser Anleitung zeige ich Ihnen, wie Sie in 7 klar strukturierten Schritten eine vollständige REST API mit Node.js und Express erstellen. Jeder Schritt enthält funktionierenden Code, den Sie direkt kopieren und anpassen können.
Node.js und Express sind die beliebteste Kombination für Backend-Entwicklung: Express verzeichnet über 30 Millionen wöchentliche npm-Downloads und wird von Unternehmen wie Netflix, Uber und PayPal eingesetzt. Wenn Sie als Entwickler auf dem Arbeitsmarkt 2026 bestehen wollen, ist REST-API-Entwicklung eine unverzichtbare Fähigkeit.
Schritt 1: Node.js installieren und Projekt initialisieren
Bevor Sie beginnen, stellen Sie sicher, dass Node.js (Version 18 oder höher) auf Ihrem System installiert ist. Öffnen Sie Ihr Terminal und prüfen Sie die Version:
node --version # Sollte v18+ anzeigen
npm --version # Sollte 9+ anzeigenErstellen Sie nun ein neues Verzeichnis für Ihr Projekt und initialisieren Sie es mit npm:
mkdir meine-rest-api
cd meine-rest-api
npm init -yDer Befehl npm init -y erstellt eine package.json mit Standardwerten. Diese Datei verwaltet die Abhängigkeiten und Skripte Ihres Projekts. Als Nächstes öffnen Sie die package.json und fügen Sie ein Start-Skript hinzu:
{
"name": "meine-rest-api",
"version": "1.0.0",
"type": "module",
"scripts": {
"start": "node server.js",
"dev": "node --watch server.js"
}
}Das "type": "module" aktiviert ES-Module-Syntax (import/export statt require). Das --watch-Flag startet den Server bei Code-Änderungen automatisch neu – eine eingebaute Node.js-Funktion, die seit Version 18 verfügbar ist und kein externes Tool wie Nodemon mehr benötigt.
Schritt 2: Express installieren und Server einrichten
Installieren Sie Express als Abhängigkeit:
npm install expressErstellen Sie jetzt die Haupt-Serverdatei server.js:
import express from 'express';
const app = express();
const PORT = process.env.PORT || 3000;
// Middleware: JSON-Body-Parsing
app.use(express.json());
// Basis-Route zum Testen
app.get('/', (req, res) => {
res.json({
message: 'Willkommen zur REST API!',
version: '1.0.0',
endpoints: {
aufgaben: '/api/aufgaben'
}
});
});
// Server starten
app.listen(PORT, () => {
console.log(`Server laeuft auf http://localhost:${PORT}`);
});Starten Sie den Server mit npm run dev und öffnen Sie http://localhost:3000 im Browser. Sie sollten die JSON-Antwort sehen. Damit steht das Grundgerüst Ihrer API.
Was passiert hier? express() erstellt eine neue Express-Anwendung. app.use(express.json()) aktiviert das Parsen von JSON-Request-Bodies – ohne diese Middleware könnte der Server keine JSON-Daten empfangen. app.listen() startet den HTTP-Server auf dem angegebenen Port.
Schritt 3: Datenmodell und In-Memory-Speicher erstellen
Für diese Anleitung verwenden wir ein einfaches Aufgaben-Modell (Todo) mit einem Array als Speicher. In einer produktiven Anwendung würden Sie hier eine Datenbank wie MongoDB oder PostgreSQL verwenden – das Prinzip bleibt jedoch identisch.
Erstellen Sie eine Datei daten.js:
// daten.js - In-Memory-Datenspeicher
let aufgaben = [
{
id: 1,
titel: 'Express lernen',
beschreibung: 'REST API mit Express erstellen',
erledigt: false,
erstelltAm: new Date().toISOString()
},
{
id: 2,
titel: 'Middleware verstehen',
beschreibung: 'Wie Middleware in Express funktioniert',
erledigt: false,
erstelltAm: new Date().toISOString()
}
];
let naechsteId = 3;
export function getAlleAufgaben() {
return aufgaben;
}
export function getAufgabeById(id) {
return aufgaben.find(a => a.id === id);
}
export function erstelleAufgabe(titel, beschreibung) {
const neueAufgabe = {
id: naechsteId++,
titel,
beschreibung,
erledigt: false,
erstelltAm: new Date().toISOString()
};
aufgaben.push(neueAufgabe);
return neueAufgabe;
}
export function aktualisiereAufgabe(id, updates) {
const index = aufgaben.findIndex(a => a.id === id);
if (index === -1) return null;
aufgaben[index] = { ...aufgaben[index], ...updates };
return aufgaben[index];
}
export function loescheAufgabe(id) {
const index = aufgaben.findIndex(a => a.id === id);
if (index === -1) return false;
aufgaben.splice(index, 1);
return true;
}Dieses Modul kapselt die Datenlogik sauber ab. In einer produktionsreifen Anwendung würden diese Funktionen statt auf ein Array auf eine Datenbank zugreifen. Das Interface bleibt gleich – ein sauberes Beispiel für das Repository-Pattern.
Schritt 4: GET-Routen implementieren
GET-Requests dienen dem Abrufen von Daten. Wir erstellen zwei Endpunkte: einen für alle Aufgaben und einen für eine einzelne Aufgabe per ID. Erstellen Sie die Datei routen.js:
// routen.js - API-Routen
import { Router } from 'express';
import {
getAlleAufgaben,
getAufgabeById,
erstelleAufgabe,
aktualisiereAufgabe,
loescheAufgabe
} from './daten.js';
const router = Router();
// GET /api/aufgaben - Alle Aufgaben abrufen
router.get('/aufgaben', (req, res) => {
const aufgaben = getAlleAufgaben();
res.json({
anzahl: aufgaben.length,
daten: aufgaben
});
});
// GET /api/aufgaben/:id - Einzelne Aufgabe abrufen
router.get('/aufgaben/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const aufgabe = getAufgabeById(id);
if (!aufgabe) {
return res.status(404).json({
fehler: 'Aufgabe nicht gefunden',
id: id
});
}
res.json({ daten: aufgabe });
});
export default router;Aktualisieren Sie nun die server.js, um die Routen einzubinden:
import express from 'express';
import router from './routen.js';
const app = express();
const PORT = process.env.PORT || 3000;
app.use(express.json());
// API-Routen einbinden
app.use('/api', router);
app.listen(PORT, () => {
console.log(`Server laeuft auf http://localhost:${PORT}`);
});Testen Sie die Endpunkte mit curl:
# Alle Aufgaben abrufen
curl http://localhost:3000/api/aufgaben
# Einzelne Aufgabe abrufen
curl http://localhost:3000/api/aufgaben/1
# Nicht existierende Aufgabe (404-Fehler)
curl http://localhost:3000/api/aufgaben/999Schritt 5: POST-Route zum Erstellen neuer Ressourcen
POST-Requests erstellen neue Ressourcen. Wichtig ist die Eingabevalidierung – vertrauen Sie niemals Daten vom Client. Fügen Sie in routen.js folgenden Endpunkt hinzu:
// POST /api/aufgaben - Neue Aufgabe erstellen
router.post('/aufgaben', (req, res) => {
const { titel, beschreibung } = req.body;
// Eingabevalidierung
if (!titel || typeof titel !== 'string' || titel.trim().length === 0) {
return res.status(400).json({
fehler: 'Validierungsfehler',
details: 'Das Feld "titel" ist erforderlich und darf nicht leer sein.'
});
}
if (titel.length > 200) {
return res.status(400).json({
fehler: 'Validierungsfehler',
details: 'Der Titel darf maximal 200 Zeichen lang sein.'
});
}
const neueAufgabe = erstelleAufgabe(
titel.trim(),
beschreibung?.trim() || ''
);
// 201 Created mit Location-Header
res.status(201)
.location(`/api/aufgaben/${neueAufgabe.id}`)
.json({ daten: neueAufgabe });
});Beachten Sie drei Best Practices hier: Erstens validieren wir die Eingabe vor der Verarbeitung. Zweitens geben wir den HTTP-Statuscode 201 Created zurück (nicht 200). Drittens setzen wir den Location-Header, der auf die neu erstellte Ressource verweist – ein Standard gemäß der HTTP-Spezifikation.
Testen Sie die Route:
curl -X POST http://localhost:3000/api/aufgaben \
-H "Content-Type: application/json" \
-d '{"titel": "Tests schreiben", "beschreibung": "Unit-Tests fuer API"}'Node.js-Entwickler für Ihr Team gesucht?
Programmier-Anfang vermittelt vorab geprüfte Backend-Entwickler mit Node.js, Express und REST-API-Erfahrung – schnell und zuverlässig.
Kostenloses Angebot in 24hSchritt 6: PUT- und DELETE-Routen implementieren
PUT aktualisiert eine bestehende Ressource, DELETE löscht sie. Fügen Sie beide Endpunkte in routen.js hinzu:
// PUT /api/aufgaben/:id - Aufgabe aktualisieren
router.put('/aufgaben/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const { titel, beschreibung, erledigt } = req.body;
// Pruefe ob mindestens ein Feld zum Aktualisieren vorhanden ist
if (titel === undefined && beschreibung === undefined && erledigt === undefined) {
return res.status(400).json({
fehler: 'Keine Daten zum Aktualisieren angegeben',
details: 'Senden Sie mindestens eines der Felder: titel, beschreibung, erledigt'
});
}
const updates = {};
if (titel !== undefined) updates.titel = titel.trim();
if (beschreibung !== undefined) updates.beschreibung = beschreibung.trim();
if (erledigt !== undefined) updates.erledigt = Boolean(erledigt);
const aktualisiert = aktualisiereAufgabe(id, updates);
if (!aktualisiert) {
return res.status(404).json({
fehler: 'Aufgabe nicht gefunden',
id: id
});
}
res.json({ daten: aktualisiert });
});
// DELETE /api/aufgaben/:id - Aufgabe loeschen
router.delete('/aufgaben/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
const geloescht = loescheAufgabe(id);
if (!geloescht) {
return res.status(404).json({
fehler: 'Aufgabe nicht gefunden',
id: id
});
}
// 204 No Content - Standard fuer erfolgreiche Loeschung
res.status(204).send();
});Beachten Sie den Statuscode 204 No Content bei erfolgreicher Löschung. Das ist der HTTP-Standard: Die Anfrage war erfolgreich, aber es gibt keinen Inhalt in der Antwort. Einige APIs geben stattdessen 200 mit dem gelöschten Objekt zurück – beide Varianten sind valide, 204 ist jedoch sauberer.
Testen Sie die Endpunkte:
# Aufgabe aktualisieren
curl -X PUT http://localhost:3000/api/aufgaben/1 \
-H "Content-Type: application/json" \
-d '{"erledigt": true}'
# Aufgabe loeschen
curl -X DELETE http://localhost:3000/api/aufgaben/2Schritt 7: Fehlerbehandlung und Middleware hinzufügen
Eine produktionsreife API braucht globale Fehlerbehandlung, Logging und Sicherheits-Middleware. Aktualisieren Sie die server.js mit diesen Ergänzungen:
import express from 'express';
import router from './routen.js';
const app = express();
const PORT = process.env.PORT || 3000;
// --- Middleware ---
// JSON-Parsing
app.use(express.json());
// Request-Logging
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const dauer = Date.now() - start;
console.log(
`${req.method} ${req.originalUrl} ${res.statusCode} - ${dauer}ms`
);
});
next();
});
// CORS-Header (fuer Browser-Zugriff)
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.header('Access-Control-Allow-Headers', 'Content-Type');
if (req.method === 'OPTIONS') {
return res.status(204).send();
}
next();
});
// --- Routen ---
app.use('/api', router);
// --- 404-Handler ---
app.use((req, res) => {
res.status(404).json({
fehler: 'Endpunkt nicht gefunden',
pfad: req.originalUrl,
methode: req.method,
tipp: 'Verfuegbare Endpunkte: GET /api/aufgaben'
});
});
// --- Globaler Fehler-Handler ---
app.use((err, req, res, next) => {
console.error('Unerwarteter Fehler:', err.stack);
res.status(500).json({
fehler: 'Interner Serverfehler',
nachricht: process.env.NODE_ENV === 'development'
? err.message
: 'Ein unerwarteter Fehler ist aufgetreten'
});
});
app.listen(PORT, () => {
console.log(`Server laeuft auf http://localhost:${PORT}`);
console.log(`Umgebung: ${process.env.NODE_ENV || 'development'}`);
});Der globale Fehler-Handler fängt alle unbehandelten Fehler ab und gibt eine sichere Fehlermeldung zurück. In der Entwicklungsumgebung wird die detaillierte Fehlermeldung angezeigt, in Produktion nur eine generische Nachricht – damit keine internen Details nach außen gelangen.
Wichtig: Der Fehler-Handler muss vier Parameter haben (err, req, res, next), damit Express ihn als Error-Handler erkennt. Mit drei Parametern würde er als normaler Middleware behandelt werden.
Nächste Schritte: Von der Demo zur Produktion
Sie haben jetzt eine funktionierende REST API mit allen CRUD-Operationen. Für den produktiven Einsatz sollten Sie folgende Ergänzungen in Betracht ziehen:
Datenbank anbinden: Ersetzen Sie den In-Memory-Speicher durch eine echte Datenbank. Für Node.js sind MongoDB mit Mongoose oder PostgreSQL mit Prisma beliebte Optionen.
Authentifizierung hinzufügen: Schützen Sie Ihre Endpunkte mit JWT (JSON Web Tokens) oder API-Keys. Für Express gibt es die Middleware passport.js, die über 500 Authentifizierungsstrategien unterstützt.
Validierungsbibliothek nutzen: Ersetzen Sie die manuelle Validierung durch eine Bibliothek wie zod oder joi. Diese Bibliotheken bieten typsichere Validierung mit deutlich weniger Code.
Tests schreiben: Verwenden Sie vitest oder jest zusammen mit supertest, um Ihre API-Endpunkte automatisiert zu testen. Eine gute Testabdeckung ist für jede produktive API unverzichtbar.
Rate Limiting: Schützen Sie Ihre API vor Missbrauch mit express-rate-limit. Eine einfache Konfiguration begrenzt die Anzahl der Anfragen pro IP-Adresse – essentiell für öffentliche APIs.
Wenn Sie tiefer in die Deployment-Automatisierung mit GitHub Actions einsteigen wollen, lesen Sie unsere Schritt-für-Schritt-Anleitung dazu.
Zusammenfassung: Ihre REST API auf einen Blick
In 7 Schritten haben Sie eine vollständige REST API erstellt. Hier ist die Zusammenfassung aller Endpunkte:
| Methode | Endpunkt | Beschreibung | Statuscode |
|---|---|---|---|
| GET | /api/aufgaben | Alle Aufgaben abrufen | 200 |
| GET | /api/aufgaben/:id | Einzelne Aufgabe abrufen | 200 / 404 |
| POST | /api/aufgaben | Neue Aufgabe erstellen | 201 / 400 |
| PUT | /api/aufgaben/:id | Aufgabe aktualisieren | 200 / 404 |
| DELETE | /api/aufgaben/:id | Aufgabe löschen | 204 / 404 |
Häufig gestellte Fragen
Was ist eine REST API und wofür braucht man sie?▼
Eine REST API (Representational State Transfer Application Programming Interface) ist eine Schnittstelle, die HTTP-Methoden (GET, POST, PUT, DELETE) verwendet, um Daten zwischen Client und Server auszutauschen. Sie wird für Web-Apps, Mobile-Apps, Microservices und IoT-Geräte eingesetzt und ist der Standard für moderne Softwareentwicklung.
Warum Node.js und Express für REST APIs?▼
Node.js bietet eine schnelle, non-blocking I/O-Architektur, die ideal für APIs mit vielen gleichzeitigen Anfragen ist. Express ist das beliebteste Web-Framework für Node.js mit über 30 Millionen wöchentlichen npm-Downloads. Die Kombination ermöglicht schnelle Entwicklung, große Community-Unterstützung und einfache Skalierung.
Wie lange dauert es, eine REST API mit Express zu erstellen?▼
Eine einfache REST API mit CRUD-Operationen kann in 60-90 Minuten erstellt werden. Eine produktionsreife API mit Authentifizierung, Datenbank-Anbindung, Validierung und Tests dauert 1-3 Tage. Mit Erfahrung und vorhandenen Boilerplates geht es noch schneller.
Welche Alternativen zu Express gibt es für Node.js REST APIs?▼
Beliebte Alternativen zu Express sind: Fastify (2-3x schneller, JSON-Schema-Validierung), NestJS (TypeScript-basiert, Angular-artige Architektur), Hono (ultraleicht, Edge-kompatibel), Koa (vom Express-Team, modernere API mit async/await) und Hapi (Enterprise-Features, Plugin-System). Für Anfänger bleibt Express der beste Einstieg.
Backend-Entwickler für Ihr Projekt gesucht?
Wir vermitteln erfahrene Node.js-Entwickler mit REST-API-, Datenbank- und Cloud-Erfahrung – vorab geprüft, schnell verfügbar.
Jetzt Entwickler finden