Ăśberblick
Die EkkoSearch-API ist eine Meta-Suchmaschine: Eine Abfrage wird parallel an mehrere Suchquellen geschickt, die Ergebnisse zusammengefĂĽhrt, doppelt gefundene Treffer dedupliziert und mit Quellen-Badges versehen zurĂĽckgegeben.
- Aktive Quellen: Tavily (KI-optimiert), Mwmbl (Community-Index), Marginalia (nicht-kommerzieller Web-Index), ekkocrawl (eigener Crawler-Index von ritter-systems.de)
- Optional: eigene SearXNG-Instanz (aktivierbar ĂĽber Server-Konfiguration,
EKKO_SEARXNG_URL) - enthaelt ebenfalls den ekkocrawl-Index als Engine - Auth: ritter-systems.de-Login (JWT) oder bestehender API-Key (
api_keys) - Quota: gebunden an den Login, UTC-Kalendermonat
Authentifizierung
Drei Varianten (in dieser Reihenfolge geprĂĽft):
JWT vom zentralen Login (POST /api/auth/login.php mit {"email": "...", "password": "..."}, Feld token). GĂĽltigkeit 24 h.
Session-Token aus der bestehenden users/sessions-Datenbank (OneBluDatabase-System, z. B. vom Notizzettel).
Bestehender API-Key aus der api_keys-Tabelle (z. B. Notizzettel-API-Key). Praktisch fĂĽr dauerhafte Skripte ohne JWT-Ablauf.
Gast-Zugang (ohne Login)
Ohne Login/API-Key wird die Anfrage als Gast behandelt:
die kostenlose Funktion ist nutzbar (10 Suchen/Monat, nach IP), die Nutzung wird
IP-basiert protokolliert. Bei Ăśberschreitung antwortet die API mit
402 QUOTA_EXCEEDED, einem freundlichen Hinweis und Verweis auf die Pricing-Seite
(upgrade_url, register_url im Fehler-Body).
Endpunkte
| Parameter | Typ | Pflicht | Beschreibung |
|---|---|---|---|
q | string | ja | Suchbegriff, max. 300 Zeichen |
max_results | int 1-25 | nein (Default 20) | Anzahl zurĂĽckgegebener (deduplizierter) Treffer |
offset | int ≥ 0 | nein (Default 0) | Startposition im Ergebnis-Pool (für "Suche fortsetzen"/Blättern) |
Alternativ per POST mit JSON-Body: {"query": "...", "max_results": 20, "offset": 20}
offset) liefern in diesem Zeitfenster stabile
Seiten, und das Blättern verbraucht keine Suche im Kontingent (zählt nur die erste
Abfrage/das Ablaufen des Caches). Antwortfelder: total_merged (Pool-Größe),
offset, returned, has_more, next_offset.Nutzungsstand des aktuellen Monats (zählt nicht als Suche).
Ohne Login: Gast-Verbrauch der eigenen IP (plan: "guest").
Beispiel
# 1) Login (JWT holen)
curl -s -X POST https://dev-test.ritter-systems.de/api/auth/login.php \
-H "Content-Type: application/json" \
-d '{"email":"du@example.com","password":"..."}'
# 2) Suchen
curl -s "https://dev-test.ritter-systems.de/ekkosearch/api/search.php?q=berlin&max_results=5" \
-H "Authorization: Bearer $TOKEN"
# ... oder mit API-Key (ohne Ablaufdatum):
curl -s "https://dev-test.ritter-systems.de/ekkosearch/api/search.php?q=berlin" \
-H "X-API-Key: notiz_xxx..."
Antwort (Suche)
{
"success": true,
"query": "berlin",
"total_results": 20,
"total_merged": 47,
"offset": 0,
"returned": 20,
"has_more": true,
"next_offset": 20,
"results": [
{
"title": "Berlin - Wikipedia",
"url": "https://de.wikipedia.org/wiki/Berlin",
"snippet": "Berlin ist die Hauptstadt ...",
"sources": ["tavily", "mwmbl"]
}
],
"sources_used": ["tavily", "mwmbl"],
"source_errors": {"marginalia": "marginalia HTTP 429 ..."},
"usage": {
"month": "2026-09",
"used": 3,
"limit": 100,
"remaining": 97
},
"meta": {
"api": "ekkosearch",
"version": "0.1.0-dev",
"auth_via": "jwt",
"timestamp": "2026-09-03T08:00:00+00:00"
}
}
total_merged/has_more/next_offset- Pagination: Poolgröße, ob weitere Seiten existieren, Offset der nächsten Seiteresults[].sources- alle Quellen, die diesen Treffer geliefert haben (Reihenfolge: Tavily → Mwmbl → Marginalia → SearXNG)sources_used- Quellen, die in diesem Suchlauf erfolgreich antwortetensource_errors- Fehler einzelner Quellen (best-effort: andere Quellen bleiben nutzbar)usage- Verbrauchsstand nach dieser Suche
Fehlercodes
| HTTP | Code | Bedeutung |
|---|---|---|
| 400 | MISSING_QUERY | Parameter q fehlt |
| 400 | QUERY_TOO_LONG | Suchbegriff > 300 Zeichen |
| 401 | UNAUTHENTICATED | UngĂĽltiger Token/API-Key (gĂĽltig ist: neu einloggen, anderen Key nutzen oder als Gast suchen) |
| 402 | QUOTA_EXCEEDED | Limit erreicht - Gast: 10/Monat (nach IP), Free: 100/Monat. Abo-Pläne (EkkoSearch-Abo, Premium-Overall-Abo) sind unbegrenzt. Body enthält usage, role, upgrade_url, register_url |
| 502 | SOURCES_FAILED | Alle Suchquellen nicht erreichbar (Zähler wird dann nicht erhöht) |
Preismodell
| Plan | Suchen/Monat | Preis | Bedingung |
|---|---|---|---|
| Gast (ohne Login) | 10 | 0 € | kein Login nötig, Tracking nach IP, freundliche Blockierung bei Überschreitung |
| Free | 100 | 0 € | ritter-systems.de-Login (Standard) |
| EkkoSearch-Abo | unbegrenzt | 2,99 €/Monat | Projekt-Level user_project_levels(project='ekkosearch') ≥ 20 (projektbezogen) |
| Premium-Overall-Abo | unbegrenzt | 20 €/Monat | alle Dienste von ritter-systems.de ohne Beschränkung (project='overall' ≥ 20 oder Legacy role_level ≥ 20) |
Projekt-Trennung (07.09.2026): Tabelle user_project_levels (user_email, project, level) steuert je Projekt: 10=free · 20=Premium (nur dieses Projekt) · 50=Premium-Overall (alle Projekte) · 100=Admin. Wirksam wird der höchste Wert aus Projekt-Eintrag, Overall-Eintrag und Legacy role_level. Ohne Login gilt der Gast-Status (IP-basiert).
Zählung: UTC-Kalendermonat, pro erfolgreicher API-Suche (auch 0 Treffer). Fehlschläge (502) werden nicht gezählt. Das Zählerblatt liegt in der bestehenden Datenbank (search_usage, search_log).
Grenzen & Fair-Use
- Max. 25 Treffer pro Anfrage; Metasuche ist auf serverseitig freigeschaltete Quellen beschränkt.
- Einzelne Quellen können ratelimitiert sein (z. B. Marginalia öffentlicher Test-Key) - die API antwortet dann mit den verbleibenden Quellen (
source_errors). - Missbrauch (Massen-Scraping ĂĽber die API) fĂĽhrt zur Sperrung des Accounts.
Changelog
- 0.1.0-dev (2026-09-07): Pricing umbenannt: "All-inclusive-Abo" heißt jetzt Premium-Overall-Abo (auch in API-Texten). Admin/Intern-Plan aus dem öffentlichen Pricing entfernt (Admin ist rein intern).
- 0.1.0-dev (2026-09-03, Nachmittag): Eigener Web-Crawler "ekkocrawl" angebunden: durchsucht das Web kontinuierlich (robots.txt-respektierend, max 20% CPU/RAM/Disk), Index wächst laufend und fliesst als eigene Quelle in die Suchergebnisse ein.
- 0.1.0-dev (2026-09-03, Nachmittag): Pricing-Update: EkkoSearch-Abo (2,99 €/Monat) und All-inclusive-Abo (20 €/Monat) = unbegrenzte Suchen (Abo-Pläne role_level ≥ 20).
- 0.1.0-dev (2026-09-03, Nachmittag): "Suche fortsetzen"-Pagination:
offset-Parameter, Seiten à 20, Pool-Cache (15 Min, DB-Tabellesearch_pool_cache) für stabile Seiten; Blättern verbraucht keine Suche. - 0.1.0-dev (2026-09-03, Nachmittag): Gast-Zugang ergänzt (Login-Konzept ritter-systems.de): ohne Login Rolle "guest", IP-Tracking, 10 Suchen/Monat, freundliche Blockierung mit Pricing-Verweis.
- 0.1.0-dev (2026-09-03): Erste Version auf dev-test. Quellen: Tavily, Mwmbl, Marginalia (SearXNG vorbereitet). Quota 100/Monat (free), Premium 2,99 €/Monat (1.000), Login-/API-Key-Auth, usage-Endpoint.