Suchen

Erklärt · Programmierung & Entwicklung

API-Schnittstelle erklärt: REST, JSON und Webhooks

Eine API ist ein vertraglich beschriebener Zugang, über den ein Programm Daten oder Funktionen eines anderen Programms nutzt. Hier siehst du Aufbau, Anfragen, Fehlercodes, Authentifizierung und Webhooks an konkretem Code.

Haftnotizen mit Begriffen wie API, ETL und Login auf einem Holztisch

Das Wichtigste in Kürze

  • Eine API ist ein Vertrag: Sie legt fest, welche Anfragen erlaubt sind und wie die Antworten aussehen – nicht, wie der Server intern arbeitet.
  • Bei REST-artigen HTTP-APIs bestimmen URL (Ressource), Methode (Aktion) und Statuscode (Ergebnis) das Verhalten; JSON ist das übliche Datenformat.
  • fetch() wirft bei einem 404 oder 500 keinen Fehler – du musst response.ok selbst prüfen.
  • Webhooks drehen die Richtung um: Der Anbieter ruft dich bei einem Ereignis auf; eine HMAC-Signatur zeigt, dass die Nachricht echt ist.

Was ist eine API?

Eine API (Application Programming Interface) ist die Schnittstelle, über die ein Programm die Funktionen oder Daten eines anderen Programms nutzt. Sie funktioniert wie ein Vertrag: Der Anbieter beschreibt, welche Anfragen er versteht und welche Antworten du bekommst. Wie er die Antwort intern erzeugt, bleibt verborgen.

Wenn im Alltag von einer „API-Schnittstelle“ die Rede ist, ist fast immer eine Web-API gemeint: Dein Programm schickt eine HTTP-Anfrage an eine URL und erhält Daten zurück, meist als JSON. Auf diese Weise sprechen Newsletter-Tools mit dem CRM, ein Shop mit dem Versanddienstleister oder ein Automatisierungs-Workflow mit allem dazwischen. Die Mechanik ist immer dieselbe, deshalb lohnt es sich, sie einmal zu verstehen.

REST: Ressourcen, Methoden und Statuscodes

REST ist ein Architekturstil für Web-APIs. In der Praxis bedeutet er: Dinge, mit denen die API arbeitet, sind Ressourcen mit eigener URL, und die HTTP-Methode sagt, was du mit ihnen tun willst.

AnfrageBedeutungTypische Antwort
GET /tasksListe lesen200 mit JSON-Liste
GET /tasks/3Einzelnes Objekt lesen200, oder 404 wenn es fehlt
POST /tasksNeues Objekt anlegen201 mit dem neuen Objekt
PUT /tasks/3Objekt ersetzen200 oder 204
PATCH /tasks/3Objekt teilweise ändern200 oder 204
DELETE /tasks/3Objekt löschen204 ohne Inhalt

Die Eigenschaften der Methoden sind festgelegt (Stand der MDN-Dokumentation am 28.10.2026):

MethodeSicher (safe)IdempotentCachebar
GETjajaja
POSTneinneinnur mit expliziten Frische-Informationen und passendem Content-Location-Header
PUTneinjanein
PATCHneinneinnur unter denselben Bedingungen wie POST
DELETEneinjanein

„Sicher“ heißt: Die Anfrage verändert nichts auf dem Server. „Idempotent“ heißt: Wiederholst du dieselbe Anfrage, ist der Zustand danach derselbe wie nach der ersten. Das ist praktisch relevant: Ein abgebrochenes PUT oder DELETE kannst du bedenkenlos wiederholen, ein abgebrochenes POST kann dagegen einen zweiten Datensatz erzeugen. Prüfe in der Dokumentation, ob der Anbieter dafür einen Idempotenz-Schlüssel anbietet.

Statuscodes lesen

Der Statuscode sagt dir, ob und warum eine Anfrage funktioniert hat. Die wichtigsten, mit den Bedeutungen laut MDN:

CodeNameBedeutung
200OKAnfrage erfolgreich
201CreatedNeue Ressource wurde angelegt
204No ContentErfolg, aber kein Inhalt zu senden
400Bad RequestServer kann oder will die Anfrage wegen eines Clientfehlers nicht verarbeiten (z. B. ungültiges JSON)
401UnauthorizedGemeint ist „nicht authentifiziert“: Du musst dich ausweisen
403ForbiddenDu bist bekannt, hast aber keine Berechtigung
404Not FoundDie Ressource wurde nicht gefunden
409ConflictDie Anfrage kollidiert mit dem aktuellen Zustand
422Unprocessable ContentAnfrage ist wohlgeformt, aber inhaltlich nicht verarbeitbar
429Too Many RequestsZu viele Anfragen in einem Zeitraum (Rate Limit)
500Internal Server ErrorAllgemeiner Serverfehler
503Service UnavailableServer vorübergehend nicht bereit, z. B. Wartung oder Überlastung

Als Faustregel: 2xx heißt Erfolg, 4xx liegt an deiner Anfrage, 5xx am Server. Bei 5xx und 429 lohnt sich ein Wiederholungsversuch mit Wartezeit, bei 4xx wie 400 oder 404 nicht – dort musst du die Anfrage ändern.

JSON: das gemeinsame Datenformat

JSON (JavaScript Object Notation) ist ein textbasiertes Format aus Objekten ({}), Listen ([]), Strings, Zahlen, Booleans und null. Fast jede Programmiersprache kann es lesen und schreiben. Beim Senden setzt du den Header Content-Type: application/json, damit der Server den Body richtig interpretiert.

JSON
{
  "items": [{ "id": 1, "title": "Newsletter planen", "done": false }],
  "page": 1,
  "total": 2
}

Eine API in der Praxis aufrufen

Damit die Beispiele nachvollziehbar sind, läuft die API hier nicht bei einem Drittanbieter, sondern als kleiner Test-Server auf deinem Rechner. Er kennt GET /tasks, POST /tasks und GET /tasks/<id>, verlangt einen Bearer-Token und liefert die Statuscodes aus der Tabelle oben. Der Server selbst ist nur Kulisse; wichtig ist der Client-Teil.

Mit curl

Shell
curl -i -H "Authorization: Bearer demo-token" "http://localhost:8787/tasks?limit=1&page=1"
Text
HTTP/1.1 200 OK
Content-Type: application/json

{"items":[{"id":1,"title":"Newsletter planen","done":false}],"page":1,"total":2}

(Weitere Header wie Date und Connection sind hier weggelassen.) Ohne den Authorization-Header antwortet der Server mit 401. Ein POST mit JSON-Body:

Shell
curl -i -X POST -H "Authorization: Bearer demo-token" -H "Content-Type: application/json" \
  -d '{"title":"Test"}' http://localhost:8787/tasks
Text
HTTP/1.1 201 Created
Content-Type: application/json
Location: /tasks/3

{"id":3,"title":"Test","done":false}

Fehlt das Feld title, kommt 422, bei kaputtem JSON 400. Das Location-Header ist die übliche Art, die URL der neu angelegten Ressource mitzuteilen.

Mit fetch (JavaScript)

Wichtig laut MDN: fetch() lehnt das Promise bei einem Serverfehler wie 404 nicht ab. Es wird nur bei Netzwerkfehlern oder Abbrüchen abgelehnt. Du musst response.ok selbst prüfen (true bei Status 200–299).

JavaScript
const BASE = "http://localhost:8787";
const headers = { Authorization: "Bearer demo-token", "Content-Type": "application/json" };

async function api(path, options = {}) {
  const response = await fetch(BASE + path, { headers, ...options });
  if (!response.ok) {
    throw new Error(`HTTP ${response.status} bei ${path}`);
  }
  return response.json();
}

console.log(await api("/tasks?limit=1&page=1"));
console.log(await api("/tasks", {
  method: "POST",
  body: JSON.stringify({ title: "Webhook einrichten" }),
}));

try {
  await api("/tasks/99");
} catch (error) {
  console.log(error.message);
}
Text
{
  items: [ { id: 1, title: 'Newsletter planen', done: false } ],
  page: 1,
  total: 2
}
{ id: 3, title: 'Webhook einrichten', done: false }
HTTP 404 bei /tasks/99

Gegen einen echten Dienst sähe der Aufruf identisch aus, nur mit anderer Basis-URL (hier illustrativ, nicht ausgeführt):

JavaScript
const response = await fetch("https://api.example.com/v1/contacts", {
  headers: { Authorization: `Bearer ${process.env.API_TOKEN}` },
});

Mit Python (urllib aus der Standardbibliothek)

Python
import json
import urllib.request

req = urllib.request.Request(
    "http://localhost:8787/tasks/1",
    headers={"Authorization": "Bearer demo-token", "Accept": "application/json"},
)
with urllib.request.urlopen(req) as resp:
    print(resp.status, json.load(resp))
Text
200 {'id': 1, 'title': 'Newsletter planen', 'done': False}

Authentifizierung: API-Keys und OAuth 2.0

Die meisten APIs wollen wissen, wer anfragt. Zwei Verfahren begegnen dir ständig:

  • API-Key oder Token: ein geheimer String, den du im Header mitsendest (häufig Authorization: Bearer …). Er ist ein Passwort für ein Programm. Lege ihn nie in Frontend-Code, in ein öffentliches Repository oder in eine URL; lies ihn aus Umgebungsvariablen oder einem Secret-Speicher. Alles, was im Browser ankommt, kann jeder Besucher auslesen.
  • OAuth 2.0: ein Framework, mit dem eine Anwendung eingeschränkten Zugriff auf einen HTTP-Dienst erhält, entweder im Namen eines Nutzers nach dessen Zustimmung oder in eigenem Namen (so fasst RFC 6749 es zusammen). Du bekommst dabei kein Passwort, sondern ein Zugriffstoken mit begrenzten Rechten und begrenzter Lebensdauer. Das Verfahren steckt hinter „Mit Google anmelden“ und hinter vielen Marketing-Integrationen, bei denen du einem Tool Zugriff auf dein Konto erlaubst.

Vergib Schlüsseln nur die Rechte, die die Integration braucht, und lege für jede Integration einen eigenen an. Dann lässt sich ein kompromittierter Schlüssel widerrufen, ohne alles andere zu stören.

Rate Limits und Pagination

Anbieter begrenzen, wie viele Anfragen du pro Zeitraum stellen darfst. Wirst du gebremst, antwortet der Server mit 429 Too Many Requests. Wie lange du warten musst und ob ein Header die Wartezeit nennt, steht in der Dokumentation des jeweiligen Anbieters – verlass dich nicht auf Annahmen. Baue Wiederholungsversuche mit wachsender Wartezeit ein und frage nicht in einer engen Schleife ab.

Listen kommen selten auf einmal. Üblich ist Pagination, also seitenweises Laden. Der Test-Server oben nutzt limit und page; andere APIs liefern stattdessen einen Cursor oder eine „next“-URL. Prüfe immer, ob die Antwort vollständig war, sonst fehlen dir stillschweigend Datensätze.

Webhooks statt Polling

Beim Polling fragst du in festen Abständen: „Gibt es etwas Neues?“ Das kostet Anfragen und liefert verzögert. Ein Webhook dreht die Richtung um: Du hinterlegst beim Anbieter eine URL, und der Anbieter schickt dir bei einem Ereignis selbst eine HTTP-Anfrage (meist POST mit JSON).

Text
Polling:  Dein System ── GET /orders?since=… ──▶ Anbieter   (alle paar Minuten, meist leer)
Webhook:  Anbieter ── POST /hooks/order-created ──▶ Dein Endpunkt   (nur bei einem Ereignis)

Dein Endpunkt sollte schnell mit 200 oder 204 antworten und die eigentliche Arbeit danach erledigen. Rechne außerdem damit, dass dieselbe Nachricht mehrfach ankommt, etwa weil der Absender bei einem Timeout wiederholt. Speichere deshalb die Ereignis-ID und ignoriere Duplikate.

Webhooks mit HMAC-Signatur prüfen

Dein Endpunkt ist öffentlich erreichbar, also kann jeder dorthin senden. Viele Anbieter signieren deshalb den Body mit einem gemeinsamen Geheimnis per HMAC (Hash-based Message Authentication Code) und senden die Signatur in einem Header. Du berechnest sie mit demselben Geheimnis selbst und vergleichst. Welcher Header, welcher Hash-Algorithmus und welches Format gelten, legt jeder Anbieter fest; SHA-256 ist verbreitet. Das folgende Beispiel zeigt das Prinzip:

Python
import hashlib
import hmac
import json

SECRET = b"demo-shared-secret"  # in der Praxis aus der Umgebung lesen


def sign(body: bytes) -> str:
    return hmac.new(SECRET, body, digestmod=hashlib.sha256).hexdigest()


def is_valid(body: bytes, signature: str) -> bool:
    return hmac.compare_digest(sign(body), signature)


body = json.dumps({"event": "contact.created", "id": 42}).encode()
signature = sign(body)  # das schickt der Absender im Header

print("Original:   ", is_valid(body, signature))
print("Manipuliert:", is_valid(body.replace(b"42", b"43"), signature))
print("Falsche Sig:", is_valid(body, "0" * 64))
Text
Original:    True
Manipuliert: False
Falsche Sig: False

Zwei Details sind entscheidend. Erstens signierst du die rohen Bytes des Bodys, so wie sie ankommen – wer das JSON erst parst und neu serialisiert, verändert unter Umständen die Bytes und die Prüfung schlägt fehl. Zweitens vergleichst du mit hmac.compare_digest() statt mit ==: Die Python-Dokumentation empfiehlt das, um die Anfälligkeit für Timing-Angriffe zu verringern. Manche Anbieter senden zusätzlich einen Zeitstempel, den du gegen Wiederholungen prüfen kannst; auch das steht dann in deren Dokumentation.

Der Marketing-Blick: CRM, Newsletter und Automatisierung

Für Marketing-Teams ist die API der Weg, Systeme ohne Copy-and-paste zu verbinden. Typische Muster:

  • Formular → CRM: Ein Webhook oder eine POST-Anfrage legt aus einer Anfrage einen Kontakt an.
  • Newsletter-Tool → Auswertung: Eine nächtliche GET-Abfrage mit Pagination zieht Anmeldungen in eine Tabelle.
  • Ereignis → Benachrichtigung: Ein Webhook meldet „Bestellung erstellt“ an einen Workflow.

Achte dabei auf zwei Punkte außerhalb der Technik: Personenbezogene Daten, die du über APIs weitergibst, unterliegen weiterhin dem Datenschutzrecht – prüfe Rechtsgrundlage und Auftragsverarbeitung, dieser Artikel ist keine Rechtsberatung. Und teste neue Integrationen zuerst mit Testdaten, denn ein POST in einer Schleife kann echte Kontakte vervielfachen.

Dein nächster Schritt

Wähle einen Dienst, den du ohnehin nutzt, und öffne seine API-Dokumentation. Suche vier Dinge: Basis-URL, Authentifizierung, ein Beispiel für GET auf eine Liste und das Rate Limit. Rufe dann genau diese Liste mit curl ab und lies den Statuscode. Wenn das klappt, bist du bei jeder weiteren API ähnlich weit. Als Nächstes lohnt es sich, den Client in einer Sprache deiner Wahl zu schreiben, etwa mit den Python-Grundlagen oder typsicher mit TypeScript. Wenn du nicht weißt, wo du beginnen sollst, hilft die Entscheidungshilfe zur ersten Programmiersprache, und für Änderungen an deinem Client-Code sind die wichtigsten Git-Befehle nützlich.

Häufige Fragen

Ist jede Web-API eine REST-API?

Nein. REST ist ein Architekturstil. Viele Dienste nutzen HTTP und JSON, ohne alle REST-Prinzipien einzuhalten; im Alltag wird „REST-API“ oft nur als „HTTP-API mit JSON“ verwendet. Entscheidend ist die Dokumentation des Anbieters.

Brauche ich für eine API-Integration Programmierkenntnisse?

Für einfache Fälle nicht: Viele Automatisierungsdienste bieten fertige Konnektoren. Sobald ein Dienst keinen Konnektor hat oder du Daten umformen musst, helfen Grundkenntnisse in HTTP und JSON, wie dieser Artikel sie vermittelt.

Quellen

  1. HTTP request methods MDN Web Docs (Mozilla) · abgerufen am 28. Oktober 2026
  2. HTTP response status codes MDN Web Docs (Mozilla) · abgerufen am 28. Oktober 2026
  3. Using the Fetch API MDN Web Docs (Mozilla) · abgerufen am 28. Oktober 2026
  4. hmac – Keyed-Hashing for Message Authentication Python Software Foundation (docs.python.org) · abgerufen am 28. Oktober 2026
  5. RFC 6749: The OAuth 2.0 Authorization Framework IETF · abgerufen am 28. Oktober 2026