Einen Discovery-Aggregator bauen
Aggregiere öffentliche Inserate organisationsübergreifend mit Cursor-Pagination und ETag-Caching und überwache deinen eigenen API-Verbrauch mit dem Usage-Endpoint.
Dieser Guide zeigt, wie du einen organisationsübergreifenden Aggregator-Feed für Inserate baust — ein Portal oder eine Vergleichsseite, die öffentliche Inserate diskret und effizient abruft — und wie du deinen eigenen Verbrauch mit dem Usage-Endpoint im Blick behältst.
Welches Problem das löst: Du betreibst einen Aggregator und brauchst einen sauberen, paginierten, cachebaren Feed öffentlicher Inserate, der diskret vermarktete Objekte respektiert, plus eine Möglichkeit, deine monatliche Quota zu überwachen.
Allgemein verfügbar. Discovery (Plan 60) und Usage (Plan 61) sind live und in der öffentlichen Referenz dokumentiert — kein Feature-Flag gatet sie. Discovery gehört zum Marktplatz-Launch-Gate: vor dem öffentlichen Marktplatz-Launch liefern Aufrufe von
GET /discovery/listings403 LAUNCH_PENDING. Usage ist nicht gegatet und schon jetzt verfügbar.
Voraussetzungen
- Für Discovery: ein Publishable Key (
pk_live_…) mit Origin-Allowlist —discovery:readist auf der Publishable-Whitelist — oder ein Secret Key. - Für Usage-Monitoring: ein Secret Key (
sk_live_…) mitusage:read. Usage ist sk-only (Geschäftszahlen dürfen nicht in einem Browser-Key liegen); einpk_-Key wird mit403 INSUFFICIENT_SCOPEabgelehnt. - Ein kostenpflichtiger Plan mit API-Zugang. Vor dem öffentlichen
Marktplatz-Launch liefern Discovery-Aufrufe
403 LAUNCH_PENDING; Usage ist davon nicht betroffen.
Schritt 1 — Durch den Discovery-Feed blättern
Discovery liefert ein reduziertes DiscoveryListingDto. Diskret vermarktete,
inaktive und gesperrte Inserate sind strukturell ausgeschlossen,
Geo-Koordinaten werden auf ~110 m gerundet, und Straße/Hausnummer werden nie
zurückgegeben.
curl "https://wohno.de/api/v1/discovery/listings?city=Berlin&rooms_min=2&limit=50" \
-H "X-API-Key: pk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Origin: https://aggregator.example.com"Antwort (200, cursor-paginiert):
{
"data": [
{
"id": "9f1c2a3b-...",
"title": "Bright 2-room apartment",
"city": "Berlin",
"zip": "10115",
"rooms": 2,
"rent_max": 980,
"property_type": "apartment",
"lat": 52.53,
"lng": 13.38
}
],
"pagination": { "next_cursor": "eyJpZCI6...", "has_more": true, "limit": 50 }
}Verfügbare Filter: city, zip (1–5 Ziffern), rooms_min, rent_max,
property_type. limit ist 1–50. Reiche pagination.next_cursor als nächstes
?cursor= weiter, solange has_more true ist.
Schritt 2 — Mit ETags cachen
Jede Antwort trägt einen ETag. Speichere ihn und sende ihn als If-None-Match
zurück, um ein günstiges 304 Not Modified zu erhalten, wenn sich nichts
geändert hat — das spart Bandbreite und zählt günstiger gegen deine Quota:
curl "https://wohno.de/api/v1/discovery/listings?city=Berlin&limit=50" \
-H "X-API-Key: pk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Origin: https://aggregator.example.com" \
-H 'If-None-Match: W/"l3-1a2b3c4d5e6f7a8b"' \
-iEin 304 kommt ohne Body zurück — verwende deine gecachte Seite wieder.
Schritt 3 — Diskrete Inserate respektieren
Du musst nichts Besonderes tun: Diskret vermarktete, inaktive und gesperrte
Inserate erscheinen in diesem Feed nie (durchgesetzt durch die View
public_discovery_listings). Versuche nicht, IDs mit anderen Endpoints
gegenzuprüfen, um sie wieder offenzulegen.
Schritt 4 — Deinen Verbrauch überwachen
Rufe deine eigene Quota/deinen Verbrauch für den aktuellen Monat mit einem Secret Key ab:
curl "https://wohno.de/api/v1/usage" \
-H "X-API-Key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx"Antwort (200):
{
"data": {
"plan": "plus",
"api_requests": {
"used": 3450,
"limit": 10000,
"reset_at": "2026-07-01T00:00:00.000Z"
},
"webhook_deliveries": {
"used": 120,
"limit": 5000,
"reset_at": "2026-07-01T00:00:00.000Z"
},
"embed_impressions": {
"used": 8800,
"limit": 50000,
"reset_at": "2026-07-01T00:00:00.000Z"
}
}
}- Frage einen vergangenen Monat mit
?period=YYYY-MMab (Europe/Berlin). Ein zukünftiger Zeitraum liefert400. - Ein
limitvon-1bedeutet unbegrenzt (Premium). - Ist der Counter-Store (Redis) kurz nicht verfügbar, erhältst du statt eines
Fehlers einen Snapshot-Fallback mit
"stale": true— behandle ihn als ungefähr.
Baue eine einfache Warnung: Alarm, wenn used / limit >= 0.8. (Dieselbe Schwelle
treibt den Header X-Quota-Status: soft-warning bei jeder API-Antwort.)
Fehlerbehandlung
| Code | HTTP | Was passiert ist | Lösung |
|---|---|---|---|
VALIDATION_ERROR | 400 | limit > 50, ungültiges zip oder zukünftiges period | Query-Parameter korrigieren. |
INSUFFICIENT_SCOPE | 403 | pk_-Key auf /usage, oder fehlender Scope | Secret Key mit usage:read verwenden. |
ORIGIN_NOT_ALLOWED | 403 | Discovery-pk_-Call von nicht erlaubter Domain | Domain unter Einstellungen → API hinzufügen. |
LAUNCH_PENDING | 403 | Discovery vor dem Marktplatz-Launch aufgerufen | Ab dem Launch verfügbar; Usage ist nicht betroffen. |
RATE_LIMITED | 429 | Discovery über 300 req / 300 s | Per ETags cachen; Retry-After respektieren. |
Siehe die Konventions-Referenz.
Best Practices
- Aggressiv cachen mit ETags — Discovery ist auf 300 Requests pro 300 Sekunden rate-limitiert.
- Mit Cursorn paginieren, niemals mit Offsets; Cursor sind stabil bei gleichzeitigen Inserts/Deletes.
- Achte auf die 80-%-Linie. Verdrahte einen Usage-Alarm, bevor du das Monatslimit erreichst.
Nächste Schritte
- Einen WBS-Eignungscheck einbetten — der andere Publishable-Plan-60-Endpoint.
- Inserate auf deiner Website einbetten — deine eigenen Inserate vs. der Aggregat-Feed.
- API-Referenz — Discovery- und Usage-DTOs.