Zum Inhalt springen

Open Beta – hilf uns beim Testen! Alle Inserate sind nur Beispiele.

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.

Beta / dark-shipped. Discovery (Plan 60) ist hinter DISCOVERY_API_ENABLED und Usage (Plan 61) hinter USAGE_API_ENABLED gegated; solange sie aus sind, liefern sie 404. Beide Operationen sind x-internal und noch nicht in der öffentlichen Referenz. Usage ist GA-ready und kann unabhängig aktiviert werden. Bitte deinen WOHNO-Ansprechpartner, die benötigten Flags zu aktivieren.

Voraussetzungen

  • Für Discovery: ein Publishable Key (pk_live_…) mit Origin-Allowlist — discovery:read ist auf der Publishable-Whitelist — oder ein Secret Key.
  • Für Usage-Monitoring: ein Secret Key (sk_live_…) mit usage:read. Usage ist sk-only (Geschäftszahlen dürfen nicht in einem Browser-Key liegen); ein pk_-Key wird mit 403 INSUFFICIENT_SCOPE abgelehnt.
  • Die Flags DISCOVERY_API_ENABLED und/oder USAGE_API_ENABLED aktiviert.

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"' \
  -i

Ein 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-MM ab (Europe/Berlin). Ein zukünftiger Zeitraum liefert 400.
  • Ein limit von -1 bedeutet 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

CodeHTTPWas passiert istLösung
VALIDATION_ERROR400limit > 50, ungültiges zip oder zukünftiges periodQuery-Parameter korrigieren.
INSUFFICIENT_SCOPE403pk_-Key auf /usage, oder fehlender ScopeSecret Key mit usage:read verwenden.
ORIGIN_NOT_ALLOWED403Discovery-pk_-Call von nicht erlaubter DomainDomain unter Einstellungen → API hinzufügen.
NOT_FOUND404Das jeweilige Feature-Flag ist ausAktivierung von DISCOVERY_API_ENABLED/USAGE_API_ENABLED anfragen.
RATE_LIMITED429Discovery über 300 req / 300 sPer 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