Requests mit curl und Postman senden

Die zwei Werkzeuge, die du jeden Tag nutzen wirst, und wann du welches nimmst.

Bisher hast du Requests aus einem Browser und über die Senden-Buttons auf diesen Seiten geschickt. Das reicht für einfache GET-Requests und für sonst nichts. Um die Methode zu wählen, Header zu setzen oder einen Body zu senden, brauchst du einen richtigen Client. Fast alle, die APIs testen, nutzen am Ende zwei: curl auf der Kommandozeile und einen grafischen Client wie Postman. Diese Lektion behandelt von beiden genug, um durch den Rest des Tutorials zu kommen.

curl

curl ist ein Kommandozeilenprogramm, das einen Request schickt und die Antwort ausgibt. Es ist unter macOS, auf den meisten Linux-Systemen und unter Windows 10 und 11 vorinstalliert. Prüf es mit curl --version. Es ist auch das Format, in dem Entwickler Requests teilen: API-Dokumentationen, die Entwicklerwerkzeuge des Browsers und Postman können einen Request als curl-Befehl anzeigen oder exportieren, du musst sie also lesen können, selbst wenn du ein anderes Werkzeug bevorzugst.

Ohne Optionen gibt curl nur den Body aus. Mit -i kommen Statuszeile und Antwort-Header dazu, was du beim Testen fast immer willst:

Terminal
curl -i https://api.testingapis.com/api/health
Ausgabe
HTTP/1.1 200 OK
content-type: application/json; charset=utf-8
date: Sun, 11 Oct 2026 11:47:45 GMT
server: Kestrel
x-powered-by: TestingAPIs
transfer-encoding: chunked

{"status":"healthy","uptimeSeconds":76890,"timestamp":"2026-10-11T11:47:46Z"}

Für mehr Details gibt -v (verbose) auch den Request aus, den curl gesendet hat, markiert mit >, und die Antwort-Header, markiert mit <. Zeilen, die mit * beginnen, beschreiben die Verbindung. Nutz das, wenn sich ein Request nicht so verhält, wie du erwartest, und du genau sehen willst, was über die Leitung ging.

Terminal
curl -v https://api.testingapis.com/api/health
Ausgabe (gekürzt)
* Host api.testingapis.com:443 was resolved.
* IPv4: 135.13.233.203
* Established connection to api.testingapis.com (135.13.233.203 port 443)
* using HTTP/1.x
> GET /api/health HTTP/1.1
> Host: api.testingapis.com
> User-Agent: curl/8.18.0
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< content-type: application/json; charset=utf-8
< date: Sun, 11 Oct 2026 11:49:47 GMT
< transfer-encoding: chunked
...

curl hat drei Header hinzugefügt, nach denen du nicht gefragt hast: Host, User-Agent und Accept. Jeder Client fügt einige Standardwerte hinzu, und verschiedene Clients fügen verschiedene hinzu. Wenn derselbe Request in Postman funktioniert und in curl scheitert, ist oft ein Standard-Header der Grund.

Methode, Header und Body

Drei Optionen decken die meisten Requests ab. -X setzt die Methode. -H fügt einen Header hinzu und lässt sich wiederholen. -d sendet einen Body. Das hier schickt ein POST mit JSON-Body an einen Endpunkt, der zurückgibt, was er bekommen hat:

Terminal
curl -X POST https://api.testingapis.com/api/methods/post \
  -H "Content-Type: application/json" \
  -d '{"name":"Asha","role":"tester"}'
Ausgabe
{"method":"POST","message":"POST request received","path":"/api/methods/post","query":{},"contentType":"application/json","bodyLength":31,"bodyTruncated":false,"body":"{\"name\":\"Asha\",\"role\":\"tester\"}","timestamp":"2026-09-30T18:31:16Z"}

Der Backslash am Ende jeder Zeile lässt den Befehl in bash und zsh in der nächsten Zeile weiterlaufen. Der Body steht in einfachen Anführungszeichen, damit die Shell die doppelten darin in Ruhe lässt. Vergisst du den Header Content-Type, schickt curl application/x-www-form-urlencoded, weil -d für HTML-Formulare gedacht war, und viele APIs lehnen den Body dann ab.

Ab curl 7.82 gibt es eine Abkürzung, --json, die den Body sendet, Content-Type: application/json und Accept: application/json setzt und die Methode auf POST umstellt. Das hier legt ein echtes Todo an:

Terminal
curl --json '{"title":"Learn curl","completed":false,"userId":1}' \
  https://api.testingapis.com/api/Todos
Ausgabe
{"message":"Todo created successfully","data":{"id":31,"userId":1,"title":"Learn curl","completed":false,"priority":"medium","dueDate":""}}

Die ID, die du zurückbekommst, ist eine andere, weil auch andere Todos anlegen. Für PUT oder PATCH ergänzt du -X PUT oder -X PATCH neben --json.

Zeitmessung und Skripte

-w gibt nach der Antwort Werte aus, die curl gemessen hat. Zusammen mit -s (still, ohne Fortschrittsbalken) und -o /dev/null (Body verwerfen) bekommst du eine einzeilige Zusammenfassung:

Terminal
curl -s -o /dev/null \
  -w "status %{http_code}  total %{time_total}s  size %{size_download} bytes\n" \
  https://api.testingapis.com/api/Products
Ausgabe
status 200  total 0.382512s  size 5846 bytes

Unter Windows nimmst du -o NUL statt -o /dev/null. time_total enthält DNS-Auflösung, Verbindungsaufbau und TLS, deshalb ist der erste Request oft langsamer als die folgenden. Die Lektion zur Performance schlüsselt diese Zahl weiter auf.

curl unter Windows

Windows braucht einen eigenen Abschnitt, weil sich derselbe Befehl je nach Shell auf drei Arten verhalten kann.

In Windows PowerShell 5.1 (der Version, die mit Windows kommt) ist curl nicht curl. Es ist ein Alias für Invoke-WebRequest, einen PowerShell-Befehl mit anderen Optionen, deshalb scheitert curl -i mit einem verwirrenden Fehler. Tipp curl.exe, um das echte Programm zu starten. PowerShell 7 hat den Alias entfernt, aber curl.exe funktioniert in beiden, also ist es eine gute Gewohnheit.

Anführungszeichen sind das zweite Problem. Windows PowerShell 5.1 entfernt doppelte Anführungszeichen innerhalb von Argumenten, wenn es sie an Programme wie curl.exe weitergibt. Der Befehl unten sieht richtig aus, und der Server bekommt kaputtes JSON:

PowerShell 5.1
PS> curl.exe -s -X POST https://api.testingapis.com/api/methods/post -H "Content-Type: application/json" -d '{"name":"Asha"}'
{"method":"POST", ... "bodyLength":11, ... "body":"{name:Asha}", ...}

Der Body kam als {name:Asha} an, und das ist kein JSON. PowerShell 7.3 und neuer reichen die Anführungszeichen korrekt durch. Bei älteren Versionen ist die schmerzloseste Lösung, den Body in eine Datei zu schreiben und curl mit @ darauf zu verweisen. Die Anführungszeichen um "@body.json" verhindern, dass PowerShell das @ als eigene Syntax behandelt.

PowerShell
# body.json contains {"name":"Asha","role":"tester"}
curl.exe -s --json "@body.json" https://api.testingapis.com/api/methods/post

In der alten Eingabeaufforderung (cmd.exe) bedeuten einfache Anführungszeichen nichts, also pack den Body in doppelte und maskier die darin mit einem Backslash. Das Zeichen für die Zeilenfortsetzung ist ^ statt eines Backslashs:

Eingabeaufforderung
curl -X POST https://api.testingapis.com/api/methods/post ^
  -H "Content-Type: application/json" ^
  -d "{\"name\":\"Asha\",\"role\":\"tester\"}"

Postman und andere grafische Clients

Ein grafischer Client erledigt dieselbe Aufgabe wie curl, nur mit einem Formular statt eines Befehls: Methode aus einem Dropdown wählen, URL eintippen, Header und Body in Tabs ausfüllen, auf Send klicken. Die Antwort erscheint darunter, formatiert, mit Status, Zeit und Größe. Postman ist am weitesten verbreitet. Insomnia und Bruno funktionieren genauso, und Bruno speichert alles als einfache Dateien, was manche Teams bevorzugen, weil die Requests dann im selben Git-Repository wie der Code liegen können. Die Ideen unten gelten für alle, mit den Begriffen aus Postman.

Collections

Eine Collection ist eine gespeicherte Gruppe von Requests, meist eine pro API, mit Ordnern darin. Sie ist der Grund, bei einem Projekt, an dem du monatelang arbeitest, einen grafischen Client statt curl zu wählen. Du baust die Requests einmal auf und teilst die Collection mit dem Team.

Du musst sie nicht von Hand bauen. Diese API veröffentlicht ein OpenAPI-Dokument, eine maschinenlesbare Beschreibung jedes Endpunkts, unter https://api.testingapis.com/openapi/v1.jsonanmelden zum Anzeigen. Wähl in Postman Import, füg diese URL ein, und es legt eine Collection mit einem Request pro Endpunkt an. Die meisten APIs, die du im Job testest, haben eine ähnliche Datei, und sie ist der schnellste Einstieg in eine unbekannte API.

Environments und Variablen

Echte Projekte betreiben dieselbe API an mehreren Orten: auf dem Laptop eines Entwicklers, auf einem Testserver, in Staging, in Produktion. Die Requests sind bis auf Basis-URL und Zugangsdaten gleich. Postman löst das mit Environments. Leg eines namens "testingapis" mit einer Variablen baseUrl auf https://api.testingapis.com an und schreib deine Request-URLs als {{baseUrl}}/api/Products/1. Wechselst du das Environment, wechseln alle Requests auf einmal. Pack auch Tokens in Variablen, damit sie nicht in Dutzende Requests kopiert werden.

Tests in Postman

Jeder Request hat einen Tab Tests (in neueren Versionen Scripts, mit einem Abschnitt post-response), in dem du JavaScript schreiben kannst, das nach Eingang der Antwort läuft. Für GET {{baseUrl}}/api/Products/1:

Postman-Test
pm.test("status is 200", function () {
  pm.response.to.have.status(200);
});

pm.test("product 1 has a price", function () {
  const product = pm.response.json();
  pm.expect(product.id).to.eql(1);
  pm.expect(product.price).to.be.a("number");
});

Die Ergebnisse erscheinen in einem Tab Test Results neben der Antwort. Der Collection Runner kann dann jeden Request einer Collection ausführen und melden, welche Prüfungen gescheitert sind. Das ist ein sanfter erster Schritt in die Automatisierung. Die Lektion zur Automatisierung zeigt, wie du Tests als gewöhnlichen Code schreibst, was besser skaliert, sobald du mehr als ein paar Dutzend hast.

Welches du nimmst

Beide, für verschiedene Aufgaben.

SituationBessere Wahl
Schnell eine Sache prüfen oder einen Bug-Report nachstellencurl
Einen exakten Request in einem Ticket oder Chat teilencurl (jeder kann ihn einfügen und ausführen)
Eine API erkunden, die du noch nicht kennstGrafischer Client mit OpenAPI-Import
Lange JSON-Bodies, die du immer wieder bearbeitestGrafischer Client
Zwischen Test- und Staging-Servern wechselnEnvironments im grafischen Client
In einem Skript oder auf einem Build-Server laufen lassencurl oder Tests als Code
Rohe Header und Verbindungsdetails ansehencurl -v

Noch eine Möglichkeit speziell für diese API: Jede Endpunktseite in der API-Referenz hat ein Formular zum Senden des Requests und zeigt einen fertigen curl-Befehl zum Kopieren. Das ist oft der schnellste Weg, einen Endpunkt auszuprobieren, bevor du ihn irgendwo speicherst.

  • Wenn ein Bug-Report einen Request enthält, häng ihn als curl-Befehl an. Der Entwickler kann ihn ausführen, ohne etwas zu importieren, und es gibt keinen Zweifel, welche Header gesendet wurden.
  • Postman wandelt in beide Richtungen um. Füg einen curl-Befehl in den Import-Dialog ein, um einen Request zu bekommen, oder nutz den Code-Button eines Requests, um curl zu bekommen.

Übung

Mach das mit curl und wiederhol es dann in einem grafischen Client.

  • Schick GET /api/echo/headers und vergleich die Header, die curl sendet, mit denen deines grafischen Clients. Welche Header hat jedes Werkzeug von sich aus hinzugefügt?
  • Leg mit POST /api/Todos ein Todo an und hol es dann mit GET /api/Todos/, gefolgt von der ID aus der Antwort.
  • Schick denselben POST ohne den Header Content-Type. Welcher Status und Body kommen zurück?
  • Miss mit -w /api/Products und /api/Products?delay=2. Der Parameter delay lässt den Server warten, der zweite sollte also etwa zwei Sekunden länger dauern.

Leg in deinem grafischen Client ein Environment mit einer Variablen baseUrl an und schreib einen Test, der absichtlich scheitert, damit du weißt, wie ein Fehlschlag aussieht, bevor du dich auf ein Bestehen verlässt.

Üben und weitergehen