APIs: Die Kellner des Internets, die ständig missverstanden werden
APIs sind überall.
Auf dem Handy. Im Browser. In Apps. In Smart-Home-Systemen. In Buchhaltungstools. In Wetter-Widgets. In diesen traurigen Unternehmensportalen, bei denen man nach dem Login sofort merkt, dass irgendwo ein Backend weint.
Und trotzdem klingen APIs für viele immer noch wie etwas, das nur Menschen mit Hoodie, Koffeinproblem und einer beunruhigend engen Beziehung zu Terminalfenstern verstehen.
Dabei ist eine API im Kern gar nicht so kompliziert.
Eine API ist eine Schnittstelle.
Also ein geregelter Weg, wie ein Programm mit einem anderen Programm spricht.
Das ist alles.
Natürlich hat die IT daraus wieder einen ganzen Zoo gebaut: REST, GraphQL, SOAP, JSON, XML, OAuth, Tokens, Rate Limits, Webhooks, Versionierung, Statuscodes, CORS und andere Begriffe, die klingen, als hätte jemand einen Router in einen Scrabble-Beutel geworfen.
Aber im Kern bleibt es simpel:
Ein Programm fragt etwas.
Ein anderes Programm antwortet.
Wenn alles gut läuft.
Wenn nicht, kommt 500 Internal Server Error, und irgendwo sagt jemand: „Komisch, bei mir lokal ging’s.“
Inhaltsverzeichnis
- Was ist eine API?
- Warum APIs überall sind
- HTTP: Die Sprache der Web-APIs
- REST oder die Kunst, Dinge vernünftig zu benennen
- JSON: Das Laminat der Datenformate
- Statuscodes: Die Ampel des Backends
- Wir bauen eine kleine API mit FastAPI
- Projektstruktur
- Der erste Endpunkt
- Datenmodell mit Pydantic
- CRUD ohne Datenbank
- Fehler sauber zurückgeben
- Authentifizierung mit API-Key
- curl: Testen wie ein Erwachsener
- Was diese API noch nicht kann
- Fazit
1. Was ist eine API?
API steht für Application Programming Interface.
Auf Deutsch: Programmierschnittstelle.
Das klingt sofort nach DIN-Ordner, Fachabteilung und einem Meeting, das auch eine E-Mail hätte sein können. Deshalb bleiben wir lieber bei API.
Eine API legt fest, wie Software miteinander spricht.
Wenn du eine Wetter-App öffnest, hat diese App nicht selbst kleine Wetterfrösche im Gerät. Sie fragt einen Wetterdienst über eine API:
Wie wird das Wetter in Hannover?
Der Wetterdienst antwortet:
8 Grad, Regen, Wind, also Hannover.
Wenn du in einer Shopping-App eine Bestellung aufgibst, redet die App mit APIs für Produkte, Warenkorb, Zahlung, Versand und wahrscheinlich noch acht Trackingdiensten, die wissen möchten, ob du bei „Socken, 3er-Pack“ emotional gezögert hast.
Wenn dein Smart-Home-System eine Lampe einschaltet, geht auch irgendwo eine API-Anfrage los.
Und wenn die Lampe nicht reagiert, nennt man das Fortschritt.
Eine API ist also nicht magisch. Sie ist ein Vertrag.
Nicht juristisch. Technisch.
Sie sagt:
- Diese Adresse kannst du aufrufen.
- Diese Daten musst du schicken.
- Diese Antwort bekommst du zurück.
- Wenn du Unsinn machst, bekommst du einen Fehler.
Im besten Fall ist dieser Vertrag gut dokumentiert.
Im schlechtesten Fall gibt es eine Wiki-Seite von 2018, drei veraltete Beispiele und einen Entwickler, der sagt: „Das müsste eigentlich gehen.“
Dann weiß man: Es wird ein langer Tag.
2. Warum APIs überall sind
Früher war Software oft ein großer Klotz.
Ein Programm. Eine Datenbank. Ein Server. Eine Oberfläche. Alles zusammen. Wenn es kaputtging, ging wenigstens alles kaputt. Das war ehrlich.
Heute besteht Software oft aus vielen Teilen.
Frontend hier. Backend da. Authentifizierung woanders. Zahlungsdienst extern. E-Mail-Versand über Dienstleister. Suche über eigene Engine. Dateien in der Cloud. Monitoring in noch einer Cloud. Und irgendwo ein Kubernetes-Cluster, das nachts Geräusche macht.
APIs halten diesen ganzen Zirkus zusammen.
Sie sind die Kellner des Internets.
Das Frontend sagt:
Ich hätte gern die Liste der letzten Blogartikel.
Die API geht in die Küche, fragt die Datenbank, richtet alles in JSON an und bringt es zurück.
Das Frontend sagt:
Danke, aber bitte ohne Passwort-Hash.
Die API sagt hoffentlich:
Natürlich.
Wenn nicht, nennt man das Datenpanne.
APIs machen Systeme modular. Man kann eine App bauen, die mit einem Backend spricht. Man kann mehrere Frontends an dieselbe API hängen. Eine Website. Eine Mobile App. Ein internes Dashboard. Ein kleines CLI-Tool für Leute, die grafische Oberflächen als persönliche Beleidigung empfinden.
APIs ermöglichen Automatisierung.
Statt irgendwo manuell Daten einzutragen, kann ein System sie senden. Statt Tabellen per E-Mail herumzuschubsen, können Systeme miteinander reden. Statt Menschen mit Copy & Paste zu quälen, quält man jetzt Entwickler mit OAuth.
Fortschritt ist relativ.
3. HTTP: Die Sprache der Web-APIs
Die meisten modernen APIs im Web sprechen HTTP.
HTTP kennst du vom Browser. Jede Website wird darüber geladen. Aber HTTP kann mehr als nur Webseiten ausliefern. Es ist auch hervorragend geeignet, strukturierte Anfragen zu senden und Antworten zurückzubekommen.
Eine HTTP-Anfrage besteht grob aus:
- Methode
- URL
- Headern
- optionalem Body
Die Methode sagt, was du ungefähr willst.
Die URL sagt, worauf du es anwenden willst.
Header enthalten Zusatzinformationen.
Der Body enthält Daten, wenn du welche mitschickst.
Ein Beispiel:
GET /articles HTTP/1.1
Host: api.example.com
Accept: application/json
Das heißt:
Gib mir bitte die Artikel. Am liebsten als JSON. Und benimm dich.
Eine Antwort könnte so aussehen:
HTTP/1.1 200 OK
Content-Type: application/json
[
{
"id": 1,
"title": "DNS: Das Telefonbuch des Internets"
}
]
Das ist im Grunde ein Gespräch.
Nur ohne Smalltalk.
Und ohne „Ich hoffe, diese Mail findet dich gut“.
Allein dafür muss man HTTP mögen.
4. REST oder die Kunst, Dinge vernünftig zu benennen
REST steht für Representational State Transfer.
Das klingt wie ein Begriff, den jemand erfunden hat, damit Konferenzfolien wichtiger wirken.
In der Praxis meint REST meistens: Wir behandeln Dinge als Ressourcen und sprechen sie über URLs an.
Zum Beispiel:
GET /articles
GET /articles/42
POST /articles
PUT /articles/42
DELETE /articles/42
Das ist schön lesbar.
GET /articles holt alle Artikel.
GET /articles/42 holt Artikel 42.
POST /articles erstellt einen neuen Artikel.
PUT /articles/42 ersetzt oder aktualisiert Artikel 42.
DELETE /articles/42 löscht Artikel 42.
Klar. Verständlich. Fast schon verdächtig.
Natürlich schaffen es Teams trotzdem, APIs zu bauen wie:
POST /doArticleAction
POST /getArticleById
GET /deleteUserFinalReallyNow
Das ist dann kein REST.
Das ist ein Hilferuf.
Gute API-Strukturen sind nicht nur schön. Sie helfen beim Denken. Wenn URLs sauber benannt sind, versteht man schneller, was passiert. Wenn Methoden sinnvoll verwendet werden, muss man nicht jedes Mal raten, ob POST /user/updateThing jetzt Daten holt, ändert oder versehentlich einen Praktikanten alarmiert.
REST ist keine Religion.
Aber ein bisschen Ordnung schadet selten.
Außer man arbeitet in historisch gewachsenen Enterprise-Systemen. Dann ist Ordnung eine ferne Sage.
5. JSON: Das Laminat der Datenformate
JSON steht für JavaScript Object Notation.
Es ist das Datenformat, das heute fast überall benutzt wird, weil es einfach, lesbar und ausreichend langweilig ist.
Ein JSON-Objekt sieht so aus:
{
"id": 1,
"title": "APIs: Die Kellner des Internets",
"published": false,
"tags": ["API", "Wissen", "Kram"]
}
Das kann man lesen.
Sogar ohne Zertifikat.
JSON besteht aus Objekten, Arrays, Strings, Zahlen, Booleans und null, also dem Datenäquivalent von „weiß ich auch nicht“.
Es ist nicht perfekt.
Datumswerte sind nervig. Kommentare gibt es nicht. Große Zahlen können je nach Sprache komisch werden. Und sobald jemand tief verschachtelte JSON-Strukturen baut, sieht das Ganze aus wie ein IKEA-Regal nach einem Umzug.
Aber JSON funktioniert.
Und in der IT gewinnt oft nicht das Schönste, sondern das, was ausreichend gut funktioniert und von genug Leuten unterstützt wird.
Also quasi das Gegenteil von Druckertreibern.
6. Statuscodes: Die Ampel des Backends
HTTP-Statuscodes sagen, wie eine Anfrage ausgegangen ist.
Die wichtigsten Gruppen:
- 2xx : Alles gut.
- 3xx : Woanders lang.
- 4xx : Du hast Mist geschickt.
- 5xx : Der Server hat Mist gebaut.
Ein paar Klassiker:
200 OK
201 Created
400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
409 Conflict
422 Unprocessable Entity
500 Internal Server Error
200 OK heißt: Hat geklappt.
201 Created heißt: Wurde erstellt.
400 Bad Request heißt: Deine Anfrage war kaputt.
401 Unauthorized heißt: Wer bist du überhaupt?
403 Forbidden heißt: Ich weiß, wer du bist, aber du darfst das trotzdem nicht.
404 Not Found heißt: Gibt es nicht.
500 Internal Server Error heißt: Der Server ist gerade innerlich umgefallen.
Gute APIs nutzen Statuscodes sinnvoll.
Schlechte APIs geben immer 200 OK zurück und schreiben dann in den Body:
{
"success": false,
"error": "Something went wrong"
}
Das ist ungefähr so hilfreich wie eine Ampel, die immer grün zeigt, aber darunter ein Schild mit „Vielleicht doch rot“ hat.
Bitte nicht.
7. Wir bauen eine kleine API mit FastAPI
Genug Theorie.
Wir bauen eine kleine API.
Nicht riesig. Kein Microservice-Drama. Keine Datenbank. Keine Container-Orchestrierung. Kein Architekturdiagramm, bei dem man danach Urlaub braucht.
Nur eine kleine API für Blogartikel.
Wir nutzen Python und FastAPI.
FastAPI ist ein modernes Python-Framework für APIs. Es ist schnell, angenehm lesbar und erzeugt automatisch eine interaktive Dokumentation. Also genau das, was viele APIs dringend bräuchten, aber aus unerklärlichen Gründen durch ein Word-Dokument in SharePoint ersetzen.
Installation:
python -m venv .venv
source .venv/bin/activate
pip install fastapi uvicorn
Unter Windows sieht die Aktivierung etwas anders aus:
python -m venv .venv
.venv\Scripts\Activate.ps1
pip install fastapi uvicorn
Danach können wir loslegen.
8. Projektstruktur
Wir halten es simpel:
api-demo/
├── main.py
└── requirements.txt
In requirements.txt schreiben wir:
fastapi
uvicorn
Und in main.py kommt unser Code.
Ja, nur eine Datei.
Für ein echtes Projekt wäre das irgendwann zu wenig. Aber für den Anfang ist eine Datei besser als ein Enterprise-Ordnerbaum mit 47 Unterverzeichnissen und keiner Ahnung, wo die Route liegt.
9. Der erste Endpunkt
Unsere erste API:
from fastapi import FastAPI
app = FastAPI(title="CODEundKRAM API")
@app.get("/")
def read_root():
return {"message": "API läuft. Noch. Bitte nichts anfassen."}
Starten:
uvicorn main:app --reload
Dann im Browser öffnen:
http://127.0.0.1:8000/
Antwort:
{
"message": "API läuft. Noch. Bitte nichts anfassen."
}
Glückwunsch.
Du hast eine API gebaut.
Noch keine gute.
Aber eine API.
Das ist wie der erste Kaffee am Montag: technisch vorhanden, emotional noch ausbaufähig.
FastAPI liefert außerdem automatisch Dokumentation:
http://127.0.0.1:8000/docs
Dort kannst du Endpunkte direkt testen.
Das ist sehr angenehm.
Und ein bisschen gefährlich, weil Menschen plötzlich Dinge anklicken, die sie nicht verstehen.
Also wie überall im Internet.
10. Datenmodell mit Pydantic
Eine API braucht Datenmodelle.
Wir wollen Blogartikel verwalten. Jeder Artikel hat:
- ID
- Titel
- Slug
- Inhalt
- Veröffentlichungsstatus
FastAPI nutzt Pydantic für Datenvalidierung.
Das heißt: Wir beschreiben, wie Daten aussehen sollen, und FastAPI prüft automatisch, ob eingehende Daten passen.
from fastapi import FastAPI
from pydantic import BaseModel, Field
app = FastAPI(title="CODEundKRAM API")
class ArticleCreate(BaseModel):
title: str = Field(min_length=3, max_length=120)
slug: str = Field(min_length=3, max_length=160)
content: str = Field(min_length=1)
published: bool = False
class Article(ArticleCreate):
id: int
ArticleCreate beschreibt die Daten, die ein Client zum Erstellen eines Artikels schicken muss.
Article erweitert das Modell um eine ID.
Wenn jemand versucht, einen Artikel mit leerem Titel zu erstellen, blockt FastAPI das automatisch.
Das ist gut.
Denn wenn man Daten nicht prüft, prüfen sie später die eigene Geduld.
11. CRUD ohne Datenbank
CRUD steht für:
- Create
- Read
- Update
- Delete
Also erstellen, lesen, ändern, löschen.
Die vier Grundnahrungsmittel jeder Verwaltungssoftware.
Wir bauen das mit einer Liste im Speicher. Keine Datenbank. Das heißt: Nach einem Neustart ist alles weg.
Also ungefähr wie manche Managemententscheidungen nach dem Quartalsmeeting.
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel, Field
app = FastAPI(title="CODEundKRAM API")
class ArticleCreate(BaseModel):
title: str = Field(min_length=3, max_length=120)
slug: str = Field(min_length=3, max_length=160)
content: str = Field(min_length=1)
published: bool = False
class Article(ArticleCreate):
id: int
articles: list[Article] = []
next_id = 1
@app.get("/")
def read_root():
return {"message": "API läuft. Noch. Bitte nichts anfassen."}
@app.get("/articles", response_model=list[Article])
def list_articles():
return articles
@app.post("/articles", response_model=Article, status_code=201)
def create_article(payload: ArticleCreate):
global next_id
article = Article(id=next_id, **payload.model_dump())
articles.append(article)
next_id += 1
return article
@app.get("/articles/{article_id}", response_model=Article)
def get_article(article_id: int):
for article in articles:
if article.id == article_id:
return article
raise HTTPException(status_code=404, detail="Artikel nicht gefunden")
@app.put("/articles/{article_id}", response_model=Article)
def update_article(article_id: int, payload: ArticleCreate):
for index, article in enumerate(articles):
if article.id == article_id:
updated = Article(id=article_id, **payload.model_dump())
articles[index] = updated
return updated
raise HTTPException(status_code=404, detail="Artikel nicht gefunden")
@app.delete("/articles/{article_id}", status_code=204)
def delete_article(article_id: int):
for index, article in enumerate(articles):
if article.id == article_id:
articles.pop(index)
return None
raise HTTPException(status_code=404, detail="Artikel nicht gefunden")
Damit haben wir eine kleine REST-API.
Endpunkte:
GET /
GET /articles
POST /articles
GET /articles/{article_id}
PUT /articles/{article_id}
DELETE /articles/{article_id}
Das ist bereits brauchbar.
Nicht produktionsreif.
Aber brauchbar.
Also schon mehr als viele interne Tools, die seit 2014 „nur vorübergehend“ laufen.
12. Fehler sauber zurückgeben
Fehler passieren.
Clients schicken Unsinn.
Server finden Dinge nicht.
Menschen löschen Artikel, die sie später doch brauchen.
Das Leben ist hart.
Eine gute API gibt Fehler sauber zurück.
Nicht so:
{
"error": "Oops"
}
Sondern verständlich:
{
"detail": "Artikel nicht gefunden"
}
Mit passendem Statuscode:
404 Not Found
FastAPI macht das mit HTTPException sehr einfach:
raise HTTPException(status_code=404, detail="Artikel nicht gefunden")
Für Validierungsfehler erzeugt FastAPI automatisch hilfreiche Antworten.
Wenn jemand zum Beispiel einen zu kurzen Titel sendet:
{
"title": "Hi",
"slug": "test-artikel",
"content": "Text",
"published": false
}
Dann kommt ein Fehler zurück, weil title mindestens drei Zeichen haben muss.
Das ist angenehm.
Und erspart einem viele manuelle Prüfungen.
Manuelle Prüfungen sind wie manuelle Buchhaltung: manchmal nötig, aber niemand sollte stolz darauf sein, wenn es anders ginge.
13. Authentifizierung mit API-Key
Unsere API ist bisher offen.
Jeder kann Artikel erstellen, ändern und löschen.
Das ist im lokalen Beispiel okay.
Im echten Internet wäre das ungefähr so klug wie ein Haustürschlüssel unter der Fußmatte mit Schild „Schlüssel hier“.
Wir bauen eine einfache API-Key-Prüfung ein.
Nicht als perfekte Sicherheitslösung. Eher als Prinzip.
from fastapi import Depends, FastAPI, Header, HTTPException
from pydantic import BaseModel, Field
API_KEY = "super-geheim-bitte-nicht-in-echt-so-machen"
app = FastAPI(title="CODEundKRAM API")
def require_api_key(x_api_key: str | None = Header(default=None)):
if x_api_key != API_KEY:
raise HTTPException(status_code=401, detail="Ungültiger API-Key")
Jetzt können wir schreibende Endpunkte schützen:
@app.post("/articles", response_model=Article, status_code=201, dependencies=[Depends(require_api_key)])
def create_article(payload: ArticleCreate):
...
Oder bei PUT und DELETE:
@app.put("/articles/{article_id}", response_model=Article, dependencies=[Depends(require_api_key)])
def update_article(article_id: int, payload: ArticleCreate):
...
@app.delete("/articles/{article_id}", status_code=204, dependencies=[Depends(require_api_key)])
def delete_article(article_id: int):
...
Der Client muss dann einen Header mitsenden:
X-API-Key: super-geheim-bitte-nicht-in-echt-so-machen
Wichtig: API-Keys gehören nicht hart in den Code.
Im echten Leben nutzt man Umgebungsvariablen, Secret-Manager oder andere Mechanismen.
Hardcoded Secrets sind wie Passwörter auf Post-its.
Nur mit Git-Historie.
Also schlimmer.
14. curl: Testen wie ein Erwachsener
Man kann APIs im Browser testen.
Man kann Tools wie Postman, Insomnia oder Bruno nutzen.
Oder man nimmt curl.
curl ist dieses kleine Kommandozeilenwerkzeug, das aussieht wie 1998, aber immer noch zuverlässig Dinge tut, während moderne Apps erst einmal ein Workspace-Update brauchen.
Artikel erstellen:
curl -X POST "http://127.0.0.1:8000/articles" \
-H "Content-Type: application/json" \
-H "X-API-Key: super-geheim-bitte-nicht-in-echt-so-machen" \
-d '{
"title": "DNS: Das Telefonbuch des Internets",
"slug": "dns-telefonbuch-des-internets",
"content": "DNS ist wichtig. Leider merkt man das meistens erst, wenn es kaputt ist.",
"published": false
}'
Alle Artikel abrufen:
curl "http://127.0.0.1:8000/articles"
Einzelnen Artikel abrufen:
curl "http://127.0.0.1:8000/articles/1"
Artikel ändern:
curl -X PUT "http://127.0.0.1:8000/articles/1" \
-H "Content-Type: application/json" \
-H "X-API-Key: super-geheim-bitte-nicht-in-echt-so-machen" \
-d '{
"title": "DNS: Immer noch meistens schuld",
"slug": "dns-immer-noch-meistens-schuld",
"content": "Der Artikel wurde aktualisiert. DNS hat zugesehen.",
"published": true
}'
Artikel löschen:
curl -X DELETE "http://127.0.0.1:8000/articles/1" \
-H "X-API-Key: super-geheim-bitte-nicht-in-echt-so-machen"
Wenn das funktioniert, hast du eine API, die man programmatisch nutzen kann.
Und falls nicht, hast du immerhin Logs.
Logs sind wie Tagebücher.
Nur ehrlicher.
15. Was diese API noch nicht kann
Unsere kleine API ist ein Lernbeispiel.
Sie kann einiges:
- Artikel auflisten
- Artikel erstellen
- Artikel abrufen
- Artikel ändern
- Artikel löschen
- Daten validieren
- einfache API-Key-Prüfung
- automatische Dokumentation
Aber sie kann auch sehr vieles nicht.
Sie hat keine Datenbank.
Nach Neustart ist alles weg.
Das ist bei Demo-Code okay. In Produktion wäre das mutig. Also dieses spezielle Mutig, das später in Postmortems landet.
Sie hat keine Benutzerverwaltung.
Ein API-Key ist nicht dasselbe wie ein echtes Auth-System mit Rollen, Berechtigungen und sauberem Token-Handling.
Sie hat kein Rate Limiting.
Niemand hindert einen Client daran, die API mit Anfragen zu bewerfen wie ein Kleinkind mit Bauklötzen.
Sie hat kein Logging-Konzept.
Keine Metriken.
Keine Tests.
Keine Datenbankmigrationen.
Keine saubere Projektstruktur.
Keine Versionierung.
Keine CORS-Konfiguration.
Keine Deployment-Strategie.
Kurz: Sie ist ein Anfang.
Und Anfänge sind gut.
Solange man sie nicht heimlich als fertige Plattform verkauft.
Für echte Projekte würde man ergänzen:
- PostgreSQL oder SQLite für Persistenz
- SQLAlchemy oder SQLModel für Datenbankzugriff
- Alembic für Migrationen
- pytest für Tests
- OAuth2 oder JWT für Authentifizierung
- CORS-Konfiguration für Browser-Clients
- Docker für reproduzierbares Deployment
- strukturierte Logs
- Monitoring
- Rate Limits
- API-Versionierung, zum Beispiel
/v1/articles
Und dann kommt irgendwann jemand und sagt:
Können wir noch schnell Mandantenfähigkeit einbauen?
Dann weiß man:
Das Projekt ist erwachsen geworden.
Oder verloren.
Manchmal beides.
16. Fazit
APIs sind keine Magie.
Sie sind Verträge zwischen Programmen.
Ein Client fragt.
Ein Server antwortet.
Dazwischen liegen HTTP, JSON, Statuscodes, Authentifizierung, Dokumentation, Validierung und gelegentlich menschliches Leid.
Gute APIs sind langweilig im besten Sinne.
Sie sind verständlich.
Vorhersehbar.
Sauber benannt.
Gut dokumentiert.
Sie liefern passende Statuscodes.
Sie validieren Daten.
Sie verstecken interne Details.
Sie tun nicht so, als sei 200 OK eine angemessene Antwort auf alles, inklusive Vollkatastrophe.
Schlechte APIs dagegen sind wie schlechte Self-Service-Portale: Man spürt, dass irgendwo jemand Arbeit sparen wollte, und leider war es nicht der Nutzer.
Mit Python und FastAPI kann man sehr schnell APIs bauen, die ordentlich wirken, gut dokumentiert sind und Spaß machen.
Das ist selten genug.
Natürlich ist der Weg von Demo-Code zu Produktion länger.
Aber wer verstanden hat, wie Endpunkte, Methoden, Modelle, Statuscodes und Authentifizierung zusammenspielen, hat den wichtigsten Schritt getan.
Der Rest ist dann nur noch Datenbank, Sicherheit, Tests, Deployment, Monitoring, Logging, Skalierung, Fehlerbehandlung, Rate Limiting, Dokumentation, Versionierung, CORS, Secrets, Backups und die Frage, warum es auf dem Server nicht läuft, obwohl es lokal ging.
Also fast nichts.
Willkommen bei APIs.
Die Kellner des Internets.
Meist unsichtbar.
Oft unterschätzt.
Und sobald sie Mist bauen, steht der ganze Laden ohne Bestellung da.
Discussion in the ATmosphere