Dokumentation

Die Einrichtung, Schritt für Schritt

Jeder Ausschnitt hier ist zum Einfügen bereit. Die Zahlen — Kontingente, Grenzen, Standardwerte, Feldnamen — stammen aus dem laufenden Code: diese Seite und der Server sagen dasselbe.

Erste Schritte

Holen Sie sich Ihren Schlüssel

Alles hier außer den RSS-Feeds verwendet einen API-Schlüssel. Öffne dein Konto, Abschnitt Entwickler-API, und kopiere ihn. Der kostenlose Plan benötigt keine Karte.

Der Schlüssel trägt deinen Plan, und dein Plan trägt deine täglichen Volumen. Zwei Zähler laufen nebeneinander: einer für die REST-API, einer für den MCP-Server. Ein Editor, der ein paar Fragen stellt, greift nie auf dein API-Budget zu.

Das Regenerieren des Schlüssels aus deinem Konto widerruft den alten sofort. Alles, was ihn noch verwendet, funktioniert nicht mehr — aktualisiere zuerst deine Integrationen.

Was brauche ich?

Du möchtest…Verwenden
Fragen Sie Ihren EditorMCP-Server
Abfragen Sie die Daten aus Ihrem eigenen CodeREST API
Informiert werden, wenn sich etwas ändertWebhooks
In n8n, Zapier oder Make integrierenAutomatisierungen
Überprüfen Sie Abhängigkeiten bei jedem Pull-RequestGitHub Action
Folgen Sie in einem Reader, kein SchlüsselRSS-Feeds

MCP-Server

Der MCP-Server, kurz erklärt

MCP (Model Context Protocol) ist eine standardisierte Methode für einen KI-Assistenten, um einen externen Dienst aufzurufen. Sie fügen eine Adresse in Ihren Client ein, und der Assistent erhält fünf Werkzeuge, die er während Ihrer Arbeit verwenden kann. Diese Werkzeuge fragen den olud.ai-Katalog ab: Open-Source-KI-Projekte, KI-Modelle mit ihren Preisen und Open-Source-Alternativen zu kommerziellen Produkten.

FaktWert
Endpunkthttps://olud.ai/mcp.php
MethodePOST, JSON-RPC 2.0. GET gibt 405 zurück (siehe unten)
TransportStreambares HTTP, ein Endpunkt, kein SSE-Stream
Protokollversion2025-06-18. Wenn der Client nach 2025-03-26 oder 2024-11-05 fragt, antwortet der Server in dieser Version
Serverversion1.0.0
SitzungKeine. Keine Mcp-Session-Id zu speichern, nichts zu verfallen, nichts zu reconnecten
Fähigkeitennur Werkzeuge. resources/list, resources/templates/list und prompts/list antworten mit leeren Listen anstelle eines Fehlers
AuthX-Api-Key-Anforderungsheader. Optional
BatchingNicht unterstützt. Ein JSON-RPC-Array wird mit HTTP 400 abgelehnt

Der Server liest. Das einzige, was er schreibt, ist Ihr täglicher Aufrufzähler.

Jede Werkzeugantwort enthält die URL der entsprechenden Seite auf olud.ai sowie eine Quellenangabe: Punkte und Indizes werden von olud.ai berechnet, kontextuelle Fakten stammen von GitHub, Hugging Face, OpenRouter, PyPI, NPM und Docker Hub.

Einrichten, Client für Client

Die gleiche URL für jeden Client: https://olud.ai/mcp.php. Der Schlüssel wird im X-Api-Key-Header übertragen. Ohne Schlüssel antwortet der Server trotzdem, mit einer kleineren Erlaubnis (25 Aufrufe pro Tag und IP, 5 Ergebnisse pro Aufruf). Ihr Schlüssel und ein bereit zum Einfügen Block befinden sich in Ihrem Konto, Abschnitt MCP-Server.

Claude Code, ein Befehl:

claude mcp add --transport http opensourceai https://olud.ai/mcp.php \
  --header "X-Api-Key: your-key"

# ohne Schlüssel:
claude mcp add --transport http opensourceai https://olud.ai/mcp.php

# überprüfen, was registriert wurde:
claude mcp list

Claude Desktop, claude_desktop_config.json:

{
  "mcpServers": {
    "opensourceai": {
      "type": "http",
      "url": "https://olud.ai/mcp.php",
      "headers": { "X-Api-Key": "your-key" }
    }
  }
}

Diese Datei befindet sich unter ~/Library/Application Support/Claude/claude_desktop_config.json auf macOS und %APPDATA%\Claude\claude_desktop_config.json auf Windows. Beenden Sie Claude Desktop und öffnen Sie es erneut, nachdem Sie es bearbeitet haben; es liest die Datei beim Start.

Wenn Claude Desktop den Server als fehlgeschlagen anzeigt oder ihn überhaupt nicht auflistet, akzeptiert Ihr Build nur lokale (stdio) Server. Verbinden Sie es mit mcp-remote, das Node installiert benötigt:

{
  "mcpServers": {
    "opensourceai": {
      "command": "npx",
      "args": ["-y", "mcp-remote", "https://olud.ai/mcp.php",
               "--header", "X-Api-Key:${OSAI_KEY}"],
      "env": { "OSAI_KEY": "your-key" }
    }
  }
}
In diesem Bridge-Block schreiben Sie X-Api-Key:${OSAI_KEY} ohne Leerzeichen nach dem Doppelpunkt und setzen den Wert in env. mcp-remote trennt ein Header-Argument an Leerzeichen, und ein inline geschriebener Header verliert seinen Wert.

Cursor, .cursor/mcp.json im Projekt (oder ~/.cursor/mcp.json für jedes Projekt):

{
  "mcpServers": {
    "opensourceai": {
      "url": "https://olud.ai/mcp.php",
      "headers": { "X-Api-Key": "your-key" }
    }
  }
}

VS Code, .vscode/mcp.json im Arbeitsbereich:

{
  "servers": {
    "opensourceai": {
      "type": "http",
      "url": "https://olud.ai/mcp.php",
      "headers": { "X-Api-Key": "${input:osaiKey}" }
    }
  },
  "inputs": [
    { "id": "osaiKey", "type": "promptString",
      "description": "olud.ai API-Schlüssel", "password": true }
  ]
}
VS Code nennt das oberste Objekt servers, nicht mcpServers. Das Kopieren des Claude- oder Cursor-Blocks so wie er ist, ist der übliche Grund, warum der Server nie erscheint. Die Eingabeaufforderung fragt beim ersten Gebrauch nach dem Schlüssel, sodass die Datei sicher bleibt, um sie zu committen.

Ein Schlüssel in der URL wie ?key=your-key funktioniert ebenfalls, da der Server ihn liest. Bevorzuge den Header: Abfragezeichenfolgen landen in der Browserhistorie, Proxy-Protokollen und der Shell-Historie.

Mit curl prüfen, ob es läuft

Wenn ein Client sagt, dass ein Server nicht verfügbar ist, teste zuerst den Server selbst. Dieser Aufruf listet die Tools auf und kostet nichts: nur tools/call verringert dein Kontingent, daher sind initialize, tools/list und ping kostenlos. Das Neustarten deines Editors verbraucht nie den Tag.

curl -s -X POST https://olud.ai/mcp.php \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: your-key" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'

Eine gesunde Antwort ist HTTP 200 mit {"jsonrpc":"2.0","id":1,"result":{"tools":[ ... ]}} und den fünf Namen darin. Als Nächstes, verbrauche einen Aufruf:

curl -s -X POST https://olud.ai/mcp.php \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: your-key" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/call",
       "params":{"name":"search_open_source_ai",
                 "arguments":{"query":"text to speech","limit":5}}}'

Ein erfolgreicher tools/call hat zwei Antwort-Header, die es wert sind, gelesen zu werden: X-RateLimit-Limit ist dein tägliches Kontingent, X-RateLimit-Remaining ist das, was nach diesem Aufruf übrig bleibt. Sie werden nur bei tools/call gesetzt.

Kürzester möglicher Lebenszeichencheck. Es antwortet {"jsonrpc":"2.0","id":0,"result":{}} und benötigt keinen Schlüssel:

curl -s -X POST https://olud.ai/mcp.php \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":0,"method":"ping"}'

Die fünf Werkzeuge

Du rufst diese nicht namentlich auf. Du stellst eine Frage, der Client wählt das Tool. Die Namen sind wichtig, wenn du ein Protokoll liest oder den Aufruf selbst schreibst, und sie werden genau abgeglichen: search_open_source_ai funktioniert, Search_Open_Source_AI nicht.

WerkzeugParameterGrenzen und StandardwerteRückgaben
search_open_source_aiquery (string, erforderlich), limit (integer)limit begrenzt auf 1 … dein Ergebnis-pro-Aufruf-Dach. Standard 10 oder dein Dach, wenn es niedriger istmatches (insgesamt gefunden, nicht abgeschnitten), dann id, name, summary, stars, language, license, github, page, health score und label, recent trend
get_projectproject (string, erforderlich)Akzeptiert einen Slug (ollama-ollama), owner/repo, eine vollständige github.com-URL oder den genauen ProjektnamenAlles oben plus owner, forks, created, pushed, topics, die vollständige Gesundheitsanalyse, gewonnene Sterne und bis zu 5 aktuelle Releases
find_alternativesproduct (string, erforderlich)Name des kommerziellen Produkts. Abgleich anhand seines Slugs, dann anhand seines genauen Namensproduct, page und die Alternativenliste, die selbst durch dein Ergebnis-pro-Aufruf-Dach begrenzt ist
list_modelsprovider (string), max_price_out (number), min_context (integer), free_only (boolean), limit (integer)provider ist ein nicht groß-/kleinschreibungssensitiver Teilstring. max_price_out ist Dollar pro Million Ausgabetokens. min_context ist in Tokens. limit begrenzt auf 1 … dein Dach, Standard 15 oder dein Dach, wenn niedrigermatches, dann id, name, provider, context, price_per_million (input und output), modality, tool_calling und die leaderboard-URL
trending_projectskind (string), limit (integer)kind ist trending, emerging oder top_health. Alles andere fällt ohne Fehler auf trending zurück. Standard trending. limit begrenzt auf 1 … dein Dach, Standard 10 oder dein Dach, wenn niedrigerkind, die Projektkarten und die Generierungszeit des Index

Fragen, die jedes Tool erreichen

  • search_open_source_ai — "Finde mir eine Open-Source-OCR-Bibliothek, die ich lokal ausführen kann."
  • get_project — "Wie gesund ist ollama/ollama gerade und wann wurde es zuletzt veröffentlicht?"
  • find_alternatives — "Welches Open-Source-Tool könnte Notion für uns ersetzen?"
  • list_models — "Welche Modelle haben mindestens 128k Kontext und kosten unter 1 $ pro Million Ausgabetokens?"
  • trending_projects — "Welche Open-Source-AI-Projekte gewinnen diese Woche am schnellsten Sterne?" Bitte nach emerging fragen, um gesunde Projekte zu erhalten, die noch wenig bekannt sind, oder nach top_health für die am besten gewarteten.
Die Suche entspricht Text, nicht Bedeutung. Es bewertet einen genauen Namen am höchsten, dann einen Namen, der mit deinen Wörtern beginnt, dann einen Namen, der sie enthält, dann eine Beschreibung, die sie enthält, und fügt Punkte für ein genaues Themen-Tag hinzu. Ein langer Satz findet nichts; "speech synthesis" findet nichts, was "text to speech" nicht findet. Wenn eine Suche leer zurückkommt, verkürze die Abfrage auf ein oder zwei Wörter.

Filter lassen das weg, was sie nicht beurteilen können. Mit max_price_out gesetzt, wird ein Modell, dessen Ausgabepreis wir nicht kennen, ausgeschlossen, anstatt geschätzt zu werden. Mit min_context gesetzt, zählt ein Modell ohne aufgezeichnetes Kontextfenster als null und wird ausgeschlossen. free_only behält Modelle, deren Stufe genau kostenlos ist.

Ein Limit über Ihrem Maximum ist kein Fehler: es wird stillschweigend begrenzt. Das veröffentlichte Schema sagt maximal 100, weil das die höchste Anzahl ist, die ein Plan erlaubt, nicht das, was Ihr Schlüssel erlaubt. Ein Limit, das keine Zahl ist, fällt auf den Standardwert zurück.

Für einige Produkte haben wir eine manuell geschriebene Vergleichsseite und keine strukturierte Liste im maschinenlesbaren Index. find_alternatives antwortet dann als Erfolg mit einem leeren Alternativen-Array, sagt, dass die strukturierte Liste für dieses Produkt nicht im Index ist, und gibt die Seiten-URL an. Ein leeres Array dort bedeutet nicht, dass keine Alternative existiert.

Volumen nach Plan

Kein SchlüsselKostenlosEntwicklerProOrg
Anrufe pro Tag252002,00020,000200,000
Ergebnisse pro Anruf5102550100

Zwei Obergrenzen, weil sie zwei verschiedene Dinge stoppen: Anfragen pro Tag begrenzen die Last, Ergebnisse pro Anfrage begrenzen, wie viel aus dem Katalog in einer Antwort herauskommt.

  • MCP-Anfragen werden separat von REST-API-Anfragen gezählt. Gleicher Schlüssel, zwei Zähler. Ein Redakteur, der ein paar Fragen stellt, berührt nie Ihr API-Budget.
  • Nur tools/call wird gezählt. initialize, tools/list und ping kosten nichts.
  • Beide Zähler setzen sich um 00:00 UTC zurück.
  • Ohne einen Schlüssel wird die Zählung pro IP-Adresse durchgeführt. Jeder hinter einer Büro-IP teilt sich die 25.
  • Bei Free und ohne Schlüssel endet jede Antwort mit einer Notizzeile, die Ihre beiden Obergrenzen angibt. Dev-, Pro- und Org-Antworten tragen keine solche Zeile.
  • Org ist der Plan, der im System als Geschäft bezeichnet wird. Fehlermeldungen drucken den internen Namen.

Wenn es nicht funktioniert

Ein fehlerhaftes Tool gibt HTTP 200 mit isError auf true und dem Grund als Klartext zurück. Das ist absichtlich: das Modell liest den Grund und kann etwas anderes versuchen. Es bedeutet auch, dass ein 200 in Ihrem Proxy-Log kein Beweis dafür ist, dass der Aufruf funktioniert hat. Lesen Sie den Body.

Schlüssel falsch eingegeben oder widerrufen. Jede Anfrage schlägt fehl mit:

Dieser API-Schlüssel ist unbekannt oder wurde widerrufen. Entfernen Sie ihn, um die kostenlose Stufe zu nutzen,
oder erhalten Sie einen neuen unter https://olud.ai/account.html

Ein fehlerhafter Schlüssel fällt nicht stillschweigend auf die anonyme Erlaubnis zurück. Beheben Sie den Schlüssel oder entfernen Sie den X-Api-Key-Header vollständig, und starten Sie dann den Client neu, damit er die Konfiguration erneut liest.

Tägliches Limit erreicht. Mit einem Schlüssel, dann ohne:

Tägliches MCP-Kontingent erreicht (200 Anfragen/Tag im "freien" Plan). Setzt sich um 00:00 UTC zurück.
Höhere Stufen: https://olud.ai/plans.html

Anonymes Limit erreicht (25 Anfragen/Tag pro IP). Setzt sich um 00:00 UTC zurück.
Ein kostenloser API-Schlüssel erhöht es auf 200/Tag — https://olud.ai/account.html

Nichts ist kaputt und nichts wird berechnet. Warten Sie auf 00:00 UTC oder steigen Sie auf. Wenn Sie keinen Schlüssel haben, bringt Sie ein kostenloser Schlüssel von 25 auf 200 Anfragen und von 5 auf 10 Ergebnisse pro Anfrage.

Toolname ist nicht eines der fünf:

Unbekanntes Tool "list_projects". Rufen Sie tools/list auf, um zu sehen, was verfügbar ist.

Ein erforderliches Argument fehlt. Jede Nachricht zeigt die Form, die sie möchte:

"query" fehlt. Beispiel: {"query": "text to speech"}
"project" fehlt. Beispiel: {"project": "ollama/ollama"}
"product" fehlt. Beispiel: {"product": "Midjourney"}

Nichts gefunden. Beide Nachrichten sagen Ihnen, wohin Sie als Nächstes gehen sollen:

Kein Projekt für "ollamaa" gefunden. Versuchen Sie zuerst search_open_source_ai, um die genaue ID zu erhalten.

Wir verfolgen "photoshop" noch nicht. Nächste Übereinstimmungen: <bis zu 8 Namen>.
Vollständige Liste: https://olud.ai/alternatives-hub.html

Der Katalog wird gerade neu aufgebaut. Warten Sie eine Minute und fragen Sie erneut; dies sind die vier Formulierungen, eine pro Datensatz:

Der Katalog wird neu aufgebaut. Versuchen Sie es in einer Minute erneut.
Diese Liste wird neu aufgebaut. Versuchen Sie es in einer Minute erneut.
Der Modellkatalog ist momentan nicht verfügbar.
Der Alternativenindex ist momentan nicht verfügbar.

Das Öffnen von https://olud.ai/mcp.php in einem Browser gibt HTTP 405 zurück. Das ist die richtige Antwort: der Endpunkt spricht JSON-RPC über POST, und die Spezifikation verlangt 405, wenn ein Server keinen GET-Stream anbietet. Der Body sagt Ihnen, was zu tun ist, und enthält die Konfiguration zum Kopieren. Er kommt in einer Zeile an; hier ist er aufgeteilt, um gelesen zu werden.

{
  "server": "olud.ai MCP",
  "version": "1.0.0",
  "protocol": "2025-06-18",
  "usage": "Dieser Endpunkt spricht MCP über JSON-RPC 2.0. POSTen Sie von einem MCP-Client aus.",
  "config": { "mcpServers": { "opensourceai": { "url": "https://olud.ai/mcp.php" } } },
  "tools": ["search_open_source_ai", "get_project", "find_alternatives",
            "list_models", "trending_projects"],
  "docs": "https://olud.ai/api.html"
}

Transportebene-Verweigerungen. Diese vier tragen einen JSON-RPC-Fehlercode, und die ersten drei tragen auch einen HTTP-Fehlercode:

405  -32600  Verwenden Sie POST mit einem JSON-RPC 2.0-Body.          (PUT, DELETE, HEAD…)
400  -32700  Parse-Fehler: der Body ist kein gültiges JSON.
400  -32600  JSON-RPC-Batching wird nicht unterstützt (in MCP 2025-06-18 entfernt).
200  -32601  Unbekannte Methode "tools/execute".
200  -32602  Fehlender Toolnamen in den Parametern.

Wenn Ihr Client sich über eine fehlende Sitzungs-ID beschwert, ignorieren Sie dies und überprüfen Sie den Transporttyp in Ihrer Konfiguration. Dieser Server speichert keine Sitzung, und es gibt keine Mcp-Session-Id, die zurückgesendet werden kann. Ein für stdio oder für SSE gegen diese URL konfigurierter Client schlägt vor dem ersten Aufruf fehl; der Typ ist http.

REST API

Authentifizierung und Schlüssel

Basis-URL: https://olud.ai/api/v1. Jeder Endpunkt ist ein GET. Der CORS-Header bewirbt POST, aber v1 hat keinen POST-Routen: Parameter werden immer aus der Abfragezeichenfolge gelesen.

Senden Sie Ihren Schlüssel im X-Api-Key-Header. Ein ?key= Abfrageparameter funktioniert auch, für einen Browser-Tab oder einen schnellen Test. Wenn beide vorhanden sind, hat der Header Vorrang. Nur /meta funktioniert ohne einen Schlüssel.

Beide Formen werden akzeptiert:

curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  "https://olud.ai/api/v1/projects?limit=3"

curl -s "https://olud.ai/api/v1/projects?limit=3&key=osk_YOUR_KEY"

Um einen Schlüssel zu erhalten: Melden Sie sich bei olud.ai an und öffnen Sie Ihre Kontoseite, Abschnitt Entwickler-API. Der Schlüssel wird bei Ihrem ersten Besuch im kostenlosen Plan erstellt und sieht aus wie osk_, gefolgt von 40 hexadezimalen Zeichen. Das Rotieren von der gleichen Seite löscht den alten Schlüssel sofort — der alte Wert gibt dann 403 invalid_key zurück.

HeaderWertGesendet am
X-RateLimit-LimitIhr tägliches Limit, als GanzzahlJede Anfrage, die den Schlüsselcheck bestanden hat
X-RateLimit-RemainingAnfragen heute übrig, auf 0 gerundetJede Anfrage, die die Schlüsselprüfung bestanden hat, einschließlich der 429
ETagQuoted md5 der Build-Zeit des ProjektgraphenJeder Endpunkt außer /meta
Access-Control-Allow-Origin*Jede Antwort, einschließlich OPTIONS (die 204 zurückgibt)
CORS ist offen und X-Api-Key ist ein erlaubter Header, sodass ein Browser die API direkt aufrufen kann. Jeder, der den Quellcode Ihrer Seite liest, hat dann Ihren Schlüssel und verbraucht Ihr Kontingent. Rufen Sie die API von Ihrem Server aus auf und geben Sie die Ergebnisse weiter.
Die Schlüsselprüfung erfolgt vor dem Routing. Ein falsch geschriebenes Pfad mit keinem Schlüssel gibt 401 missing_key zurück, nicht 404. Fügen Sie den Schlüssel hinzu, bevor Sie nach einem Tippfehler im Pfad suchen.

Antwortenumschlag

Ein Erfolg ist immer HTTP 200 mit drei obersten Schlüsseln: ok ist true, data enthält die Nutzlast, meta enthält den Kontext. data ist ein Objekt bei Endpunkten mit einem einzelnen Datensatz und ein Array bei Listenendpunkten.

GET /api/v1/meta, wörtlich:

{"ok":true,"data":{"name":"olud.ai API","version":"v1","generated":"2026-07-27T07:45:15+00:00","counts":{"projects":10142},"endpoints":["/project/{id}","/projects","/emerging","/alternatives/{id}","/search?q=","/models"],"docs":"https://olud.ai/api/"},"meta":{"attribution":"Scores & indices computed by olud.ai (olud.ai). Kontextuelle Fakten aus öffentlichen Quellen: GitHub, Hugging Face, OpenRouter, Artificial Analysis, PyPI, NPM, Docker Hub."}}

meta.attribution wird bei jeder Erfolgsantwort, bei jedem Endpunkt gesetzt und kann nicht deaktiviert werden. Der Rest von meta variiert je nach Endpunkt: generated, total, limit, offset, sort, freshness, points. Lesen Sie die Endpunktabschnitte, um herauszufinden, welche Felder Sie erhalten.

Ein Fehler enthält ok false, einen HTTP-Status ungleich 200 und error.code plus error.message. Es gibt kein meta-Objekt bei einem Fehler, also kein attribution-Feld. Testen Sie ok, bevor Sie data lesen — gehen Sie nicht davon aus, dass die Erfolgsform vorliegt.

GET /api/v1/projects ohne Schlüssel, wörtlich:

{"ok":false,"error":{"code":"missing_key","message":"Geben Sie Ihren API-Schlüssel über den X-Api-Key-Header (oder ?key=) an. Holen Sie sich einen unter https://olud.ai/api/"}}

Senden Sie den ETag als If-None-Match zurück und Sie erhalten 304 mit einem leeren Körper, wenn der Graph nicht neu aufgebaut wurde. Der Graph wird einmal jeden Morgen neu aufgebaut, sodass häufigeres Abfragen als das den ganzen Tag 304 zurückgibt.

Zwei Dinge, die Sie über den ETag wissen sollten. Er wird nur aus dem Projektgraphen berechnet, sodass derselbe Wert von /models, /hf und /history zurückgegeben wird — senden Sie einen ETag zurück an den Endpunkt, von dem Sie ihn erhalten haben, oder Sie erhalten 304, während neuere Daten dahinter liegen. Und das Kontingent wird gezählt, bevor der ETag verglichen wird, sodass ein 304 immer noch eine Anfrage kostet.

Endpunkte: Meta und Projekte

GET /meta

Graphstatus. Der einzige Endpunkt ohne Schlüssel und der einzige, der nicht gegen Ihr Kontingent zählt. Gibt den API-Namen und die Version, generated (UTC-Zeitstempel des letzten Graphenaufbaus), counts.projects, eine Liste von Endpunkten und die URL der Dokumentation zurück. Keine Parameter. Wenn die Graphdateien nicht lesbar sind, ist counts null und der Aufruf gibt trotzdem 200 zurück — verwenden Sie es als Gesundheitscheck und um zu entscheiden, ob ein erneutes Abrufen sinnvoll ist. Es sendet keinen ETag und keine Rate-Limit-Header.

curl -s https://olud.ai/api/v1/meta

GET /project/{id}

Ein Projekt, vollständiger Datensatz. Dies ist die zusammengeführte Ansicht: GitHub-Fakten, unsere Wartungsbewertung, Sternen-Velocity, Veröffentlichungen, Adoptions-Puls.

  • Identität: id, name, owner, url, page (Pfad der Projektseite auf der Website), desc.
  • GitHub-Fakten zum letzten Build: Sterne, Forks, lang, Lizenz, Themen, erstellt, gepusht.
  • health: Punktzahl von 100, Label, warum, plus die vier Komponenten, aus denen sie besteht — Aktivität (max 30), Momentum (max 20), Community (max 30), Wartung (max 20) — Gewichte v2 seit 29. Juli 2026 — und geprüft. Labels folgen der Punktzahl: 85+ Thriving, 70+ Healthy, 50+ Maintained, 30+ Slowing down, unter 30 At risk. Ein Projekt ohne Commit in vier Wochen hat seine Punktzahl auf 45 begrenzt, sodass die Komponenten mehr als die Punktzahl addieren können. Nicht jedes Projekt wird bewertet; testen Sie auf das Feld.
  • velocity: stars_1d und stars_7d, aus unserer eigenen täglichen Sternhistorie.
  • releases: tag, datum, level, url — die aktuellsten zuerst.
  • tool: slug, cat, pulse, docker_pulls, npm_month, pip_month, hn_hits, bsky_week, compare_pages. Nur für Projekte, die mit einem verfolgten Tool übereinstimmen, vorhanden.
  • rank, trend (stabil, ruhig oder beschleunigend) und Signale (stars_accel, has_page).
ParameterTypStandardVerhalten
idPfadsegment, erforderlichkeineKleinbuchstaben. Wird in drei Schritten aufgelöst: exakter slug, dann das owner/name-Index, dann owner-name. Kein Segment gibt 400 missing_id zurück; kein Treffer gibt 404 not_found mit einem Hinweis auf /search zurück.
curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  https://olud.ai/api/v1/project/ollama-ollama
Verwenden Sie den mit Bindestrich versehenen slug. Ein literales Slash im Pfad beginnt ein neues Pfadsegment, sodass /v1/project/ollama/ollama "ollama" nachschlägt und 404 zurückgibt. Die ids, die von /projects und /search zurückgegeben werden, sind immer sicher zurückzugeben.

GET /projects

Filter, sortieren und blättern Sie im Katalog. Filter werden zuerst angewendet, dann die Sortierung, dann Offset und Limit.

ParameterTyp / GrenzenStandardVerhalten
langstringkein FilterExakte Übereinstimmung mit der Projektsprache, nicht groß-/kleinschreibungsempfindlich. lang=rust behält nur Rust bei.
Lizenzstringkein FilterTeilzeichenfolgenübereinstimmung mit der Lizenz-ID, nicht groß-/kleinschreibungsempfindlich. license=gpl behält GPL-2.0 und AGPL-3.0 bei.
vertikalstringkein FilterExakte Übereinstimmung, nicht groß-/kleinschreibungsempfindlich. Werte, die im Diagramm vorhanden sind: robotik, sicherheit, finanz, wissenschaft, gesundheit, bildung, recht. Die meisten Projekte haben keine, und sie verschwinden alle, wenn Sie dies einstellen.
health_minganzzahlkein FilterBeibehaltung von Projekten, deren health.score größer oder gleich dem Wert ist. Nicht bewertete Projekte zählen als 0 und fallen heraus. Ein nicht-numerischer Wert wird zu 0, was nichts filtert.
sortierensterne, gesundheit, momentum oder aktuellsterneImmer absteigend. momentum liest velocity.stars_7d, aktuell liest das letzte Push-Datum. Ein unbekannter Wert wird nach Sternen sortiert, aber unverändert in meta.sort zurückgegeben — überprüfen Sie meta.sort, wenn die Reihenfolge Sie überrascht.
limitganzzahl 1-10025Außerhalb des Bereichs liegende Werte werden auf die Grenzen beschränkt, nicht-numerische Werte fallen auf 25 zurück. Es wird kein Fehler ausgelöst, sodass limit=500 Ihnen stillschweigend 100 gibt.
offsetganzzahl 0-1000000Wird auf die gleiche Weise beschränkt.
curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  "https://olud.ai/api/v1/projects?lang=python&license=apache&sort=health&health_min=70&limit=10"

Daten sind ein Array von kompakten Karten: id, name, url, desc, sterne, lang, lizenz, gesundheit (nur der Score), momentum (stars_7d), trend, vertikal. Felder ohne Wert sind vorhanden und null. Für die Komponenten, Veröffentlichungen und Adoptionszahlen rufen Sie /project/{id} auf. meta gibt total (Übereinstimmungen nach Filterung, vor Paging), limit, offset, sort und generiert an.

Endpunkte: Suche, Neuheiten, Alternativen

GET /search

Durchsucht Projekte nach Name, Beschreibung und Themen. Es durchsucht keine Modelle oder Hugging Face-Reihen — verwenden Sie /models und /hf dafür.

ParameterTyp / GrenzenStandardVerhalten
qstring, erforderlichkeineGetrimmt und in Kleinbuchstaben. Leer oder nur Leerzeichen gibt 400 missing_query zurück.
limitganzzahl 1-5015Auf die Grenzen beschränkt; nicht-numerische Werte fallen auf 15 zurück.
curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  "https://olud.ai/api/v1/search?q=ocr&limit=5"

Bewertung, damit Sie die Reihenfolge vorhersagen können: exakte Namensübereinstimmung 100, Name beginnt mit q 60, Name enthält q 40, Beschreibung enthält q 15, und +20, wenn q genau einem der Themen des Projekts entspricht. Gleichstände werden nach Sternen aufgelöst. Alles, was 0 Punkte hat, wird ausgeschlossen. Die Übereinstimmung erfolgt durch einfache Teilzeichenfolgen — kein Stemming, keine Tippfehler-Toleranz. Karten haben die gleiche Form wie /projects. meta gibt total (alle Übereinstimmungen, nicht die Seite) und q als normalisiert an.

GET /emerging

Der tägliche Entdeckungsindex: junge Repositories mit nachhaltigem Wachstum und, wo wir sie bewerten können, guter Gesundheit. Rangiert nach unserem Discovery Score. Karten tragen zwei zusätzliche Felder: signals und detected, das Datum, an dem das Projekt erstmals in den Index aufgenommen wurde (null, wenn unbekannt).

ParameterTyp / GrenzenStandardVerhalten
limitganzzahl 1-10025Beschränkt. Sie können weniger Zeilen erhalten, als Sie angefordert haben: IDs, die nicht mehr im Projektdiagramm vorhanden sind, werden übersprungen.
curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  "https://olud.ai/api/v1/emerging?limit=10"

Frische hängt vom Plan ab, und meta sagt, welchen Sie erhalten haben. Pro und Business lesen den Index von heute Morgen und erhalten meta.freshness "realtime". Free und Dev lesen den Snapshot von gestern und erhalten "previous-day" plus eine meta.note. Zwei Konsequenzen, die es wert sind, bekannt zu sein: Bei Free und Dev ist meta.criteria null, da der Kriterien-Text nur mit dem aktuellen Index gespeichert wird; und wenn die Snapshot-Datei von gestern fehlt, erhalten Free und Dev den aktuellen Index, während meta.freshness weiterhin "previous-day" anzeigt.

GET /alternatives/{product}

Open-Source-Alternativen zu einem kommerziellen Produkt. data gibt name, domain, desc, page, cat und ein alternatives-Array zurück, dessen Einträge name, repo, site, lizenz und desc enthalten. repo kann ein leerer String sein, wenn das Projekt kein GitHub-Repository hat. meta gibt generiert an.

ParameterTypStandardVerhalten
ProduktPfadsegment, erforderlichkeineKleinbuchstaben. Exakter Produkt-Schlüssel zuerst; falls nicht vorhanden, das erste Produkt, dessen Schlüssel oder Name deinen String enthält, in der Dateireihenfolge. Kein Segment gibt 400 missing_id zurück; kein Treffer gibt 404 not_found zurück. Übergebe den exakten Slug — den in der URL der /alternatives/<slug>.html-Seite — wenn du ein spezifisches Produkt benötigst, da lose Übereinstimmung den ersten Treffer nimmt, nicht den besten.
curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  https://olud.ai/api/v1/alternatives/notion

Endpunkte: Modelle, hf, Verlauf

GET /models

Modellkatalog, erstellt von OpenRouter. Jede Zeile: id, name, provider, tier, ctx (Kontextfenster in Tokens), price_in und price_out (US-Dollar pro Million Tokens, auf zwei Dezimalstellen gerundet, 0, wenn die Quelle keinen Preis angibt), modality (zum Beispiel text->text oder text+image+file->text), tools (boolean) und rank. Felder ohne Wert werden aus der Zeile entfernt, also überprüfe auf Vorhandensein, anstatt anzunehmen, dass price_in existiert. meta gibt total, limit, offset, generated und source an.

ParameterTyp / GrenzenStandardVerhalten
providerstringkein FilterTeilzeichenfolgenübereinstimmung, nicht groß-/kleinschreibungsempfindlich. provider=mistral entspricht "Mistral AI".
tierkostenlos oder bezahltkein FilterExakte Übereinstimmung, nicht groß-/kleinschreibungsempfindlich auf deinem Input.
limitinteger 1-20050An die Grenzen angepasst; nicht-numerische Werte fallen auf 50 zurück.
offsetganzzahl 0-1000000Angewendet auf die zusammengeführte Liste. Offene Gewichtzeilen kommen zuerst, dann proprietäre, jeder Block in Rangfolge.
curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  "https://olud.ai/api/v1/models?tier=free&provider=mistral&limit=20"
tier ist kein Preis-Flag. kostenlos bedeutet, dass die Gewichte veröffentlicht sind (offenes Gewicht), bezahlt bedeutet proprietär. Ein offenes Gewichtmodell kann einen non-zero price_in haben, da der Preis das ist, was ein API-Anbieter verlangt, um es auszuführen. Außerdem beginnt der Rang in jedem Tier wieder bei 1, sodass das Sortieren der zusammengeführten Liste nach Rang zwei Skalen mischt.

GET /hf

Hugging Face: am häufigsten heruntergeladen und im Trend. Keine Parameter. data hat drei Arrays — top_llm (Textgenerierungsmodelle nach 30-Tage-Downloads), top (alle Aufgaben, auf 30 Zeilen durch diesen Endpunkt begrenzt) und trending (heutige Aufsteiger). Jede Zeile: id, org, name, task, downloads (rollierende 30 Tage), likes, license, gated, created, updated, trend (Anstieg der Likes bei trendenden Zeilen, null anderswo). meta gibt generated und source an.

curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  https://olud.ai/api/v1/hf
Dieser Endpunkt hängt von einem morgendlichen Scan des Hugging Face Hub ab. Bevor diese Datei existiert, gibt der Aufruf 503 not_ready zurück. Nichts auf deiner Seite ist falsch; versuche es später am Tag erneut.

GET /history/{slug}

Tägliche Serie für ein Projekt: Sterne, Gesundheit und 7-Tage-Geschwindigkeit. Pro- und Business-Keys nur — der Business-Plan ist der, der als Org verkauft wird. Jeder andere Plan erhält 403 pro_required. data gibt slug, days (Daten im Format YYYY-MM-DD, älteste zuerst) und series mit drei Arrays, stars, health und velocity_7d, indexweise ausgerichtet mit days. Einzelne Einträge können null sein, wenn der Wert eines Tages fehlte. meta gibt points und window an.

ParameterTypStandardVerhalten
slugPfadsegment, erforderlichkeineKleinbuchstaben, und muss mit ^[a-z0-9][a-z0-9._-]*$ übereinstimmen — die gleiche id wie /project/{id}. Alles andere gibt 400 bad_slug zurück. Ein gültiger slug, für den noch nichts aufgezeichnet wurde, gibt 404 not_found zurück.
curl -s -H "X-Api-Key: osk_YOUR_KEY" \
  https://olud.ai/api/v1/history/ollama-ollama
meta.window liest immer "90 Tage rollierend" — das ist die Obergrenze, die zur Build-Zeit festgelegt wird, kein Versprechen von 90 Punkten. Die Aufzeichnung beginnt, wenn ein Projekt in das Diagramm eintritt, daher sind kurze Serien normal. Lies meta.points für das, was du tatsächlich erhalten hast, und dimensioniere dein Diagramm von Tagen, niemals von einem fest codierten 90.

Tägliche Quoten

Anfragen werden pro Schlüssel, pro UTC-Tag gezählt. Der Zähler wird um 00:00 UTC zurückgesetzt. Es gibt keine pro-Sekunde oder pro-Minute-Beschränkung im Code.

Plan auf dem SchlüsselAnfragen / TagÖffentlicher NameWas es ändert
kostenlos500KostenlosAlles außer /history. /emerging dient dem Index des vorherigen Tages.
dev5000EntwicklerGleicher Zugriff wie Free, höhere Obergrenze.
pro50000Pro/history öffnet. /emerging dient dem Index von heute Morgen.
business500000OrgGleicher Zugriff wie Pro, höhere Obergrenze.

Was zählt: jeder Endpunkt außer /meta, eine Einheit pro Anfrage. Der Zähler wird direkt nach der Überprüfung des Schlüssels und vor allem anderen erhöht, sodass ein 304, ein 404 not_found, ein 400 missing_query und ein 503 graph_unavailable jeweils eine Einheit kosten. Nur 401 missing_key und 403 invalid_key kosten nichts, da es keinen gültigen Schlüssel gibt, den man belasten könnte.

Ein Quotenfeld, das auf deinem Schlüssel festgelegt ist, überschreibt den Planstandard. X-RateLimit-Limit ist die Autorität über deine Obergrenze, nicht die Tabelle oben.

Über der Obergrenze gibt jede Anfrage 429 quota_exceeded zurück, bis der Reset erfolgt. Die abgelehnte Anfrage wird nicht gezählt, es wird nichts in die Warteschlange gestellt und nichts wird berechnet. Kein Retry-After-Header wird gesendet — der Reset erfolgt um 00:00 UTC.

So sieht eine abgelehnte Anfrage mit einem kostenlosen Schlüssel aus:

HTTP/2 429
X-RateLimit-Limit: 500
X-RateLimit-Remaining: 0

{"ok":false,"error":{"code":"quota_exceeded","message":"Tägliches Kontingent erreicht (500 Anfragen/Tag im \"kostenlosen\" Plan). Setzt sich um 00:00 UTC zurück."}}
Der MCP-Server unter /mcp.php hat seinen eigenen Zähler: 25 Anrufe/Tag ohne Schlüssel (pro IP gezählt), 200 im Free, 2000 im Dev, 20000 im Pro, 200000 im Business. Fragen, die Ihr Editor über MCP stellt, verbrauchen nicht das REST-Kontingent und umgekehrt.
Ein Fehlerzustand, den man erkennen sollte: Wenn die Zählerdatei nicht geöffnet werden kann, werden Anfragen durchgelassen und X-RateLimit-Remaining zeigt 0 an. Ein 200 zusammen mit Remaining: 0 bedeutet, dass der Zähler nicht verfügbar war, nicht dass Sie kein Kontingent mehr haben.

Fehlercodes

Jeder Fehler gibt error.code als stabilen String zurück. Branchen Sie darauf, nicht auf den Nachrichtentext, der Slugs und Plan-Namen enthält und sich mit der Anfrage ändert.

HTTPcodeTriggerWas zu tun ist
401missing_keyKein X-Api-Key-Header und kein ?key=. Auch das, was Sie für einen unbekannten Pfad erhalten, wenn kein Schlüssel gesendet wird, da die Schlüsselüberprüfung vor dem Routing erfolgt.Senden Sie den Schlüssel. Ein 401 auf einem Pfad, von dem Sie sicher sind, dass er existiert, ist ein fehlender Header, nicht ein falscher Pfad.
403invalid_keyDer Schlüssel ist nicht im Speicher oder sein aktives Flag ist falsch. Das Rotieren Ihres Schlüssels löscht den vorherigen.Lesen Sie den aktuellen Schlüssel von Ihrer Kontoseite und aktualisieren Sie den Aufrufer. Rotation bricht jede bereitgestellte Kopie des alten Schlüssels auf einmal.
403pro_required/history wurde mit einem kostenlosen oder Dev-Schlüssel aufgerufen.Lesen Sie die heutigen Werte von /project/{id} (Gesundheit, Geschwindigkeit) oder wechseln Sie zu Pro.
429quota_exceededDer tägliche Zähler hat Ihre Obergrenze erreicht.Hören Sie auf, bis 00:00 UTC zu rufen, oder erhöhen Sie den Plan. Lesen Sie X-RateLimit-Limit, um Ihre tatsächliche Obergrenze zu bestätigen.
400missing_id/project oder /alternatives wurde ohne Pfadsegment aufgerufen.Fügen Sie das Segment hinzu. /v1/project allein ist keine Auflistung — verwenden Sie /v1/projects.
400missing_query/search mit leerem oder nur Leerzeichen q.Senden Sie ein nicht leeres q. Beachten Sie, dass die Anfrage trotzdem gezählt wurde.
400bad_slug/history slug leer oder enthält ein Zeichen außerhalb von ^[a-z0-9][a-z0-9._-]*$.Geben Sie die ID genau so an, wie sie von /projects oder /search zurückgegeben wurde.
404not_foundUnbekannte Projekt-ID, keine Alternativen für dieses Produkt verfolgt oder keine Historie für diesen Slug gespeichert.Für ein Projekt, versuchen Sie es erneut über /search?q=. Für die Historie könnte das Projekt zu kürzlich in die Verfolgung eingetreten sein, um Punkte zu haben.
404unknown_endpointGültiger Schlüssel, Pfad nicht im Router.Überprüfen Sie die Schreibweise. /meta listet sechs Endpunkte auf und lässt /hf und /history aus, die beide existieren.
503graph_unavailableEine Graphdatei fehlt oder ist nicht lesbar, was passiert, während der morgendliche Build sie schreibt.Versuchen Sie es in einer Minute erneut. Ihr Schlüssel ist in Ordnung; rotieren Sie ihn nicht.
503nicht_bereit/hf vor dem morgendlichen Hugging Face-Scan hat seine Datei produziert.Versuchen Sie es später am Tag erneut. Andere Endpunkte sind nicht betroffen.
304kein KörperIf-None-Match stimmte mit dem aktuellen ETag überein.Dienen Sie Ihrer zwischengespeicherten Kopie. Denken Sie daran, dass dies eine Anfrage aus Ihrem Kontingent verbraucht hat.

Wiederholungsrichtlinie, die dem Code entspricht: Wiederholen bei 503 nach einer Minute und bei 429 nur nach dem UTC-Reset. Wiederholen Sie niemals einen 400, 403 oder 404 unverändert — die Antwort wird sich nicht ändern und jeder Versuch kostet eine Anfrage.

Validieren Sie die Parameter auf Ihrer Seite, bevor Sie sie senden. Werte für Limit und Offset außerhalb des zulässigen Bereichs werden stillschweigend begrenzt, anstatt abgelehnt zu werden, sodass ein schlechter Wert Ihnen eine Anfrage kostet und eine Seite zurückgibt, die Sie nicht angefordert haben. Vergleichen Sie meta.limit und meta.offset mit dem, was Sie gesendet haben, wenn ein Ergebnis kurz aussieht.

Webhooks

Einen Webhook erstellen

Ein Webhook ist ein signiertes POST an Ihren Endpunkt pro Ereignis. Sie wählen die Ereignisse, die Repositories und die Form des Körpers. Webhooks benötigen einen kostenpflichtigen Plan: Bei einem kostenlosen Schlüssel antwortet die Erstellung mit 403 paid_feature und die Kontoseite zeigt ein gesperrtes Panel anstelle des Formulars.

Plan, der von der API gemeldet wurdeWebhooks erlaubt
kostenlos0
dev3
pro10
business50

Ein Planname, den wir nicht erkennen, fällt auf 1 zurück. Sobald Sie bei Ihrer Anzahl sind, antwortet die Erstellung mit 429 limit_reached — löschen Sie einen oder ändern Sie den Plan.

Von Ihrem Konto

  • Melden Sie sich an und öffnen Sie /account.html. Die Webhooks-Karte erscheint, sobald Ihr API-Schlüssel geladen ist, und bleibt bis dahin verborgen.
  • Fügen Sie Ihren Endpunkt im URL-Feld ein. Die Seite akzeptiert nichts, was nicht mit https:// beginnt.
  • Wählen Sie die Ereignisse aus. release und health sind für Sie ausgewählt; license und new_project sind es nicht.
  • Lassen Sie das Feld für Repos leer, um alles zu erhalten, oder geben Sie Einträge im Format owner/name getrennt durch Kommas ein.
  • Wählen Sie das Ziel im Auswahlfeld: Ihren eigenen Endpunkt (raw signiertes JSON), Slack oder Discord.
  • Drücken Sie Erstellen. Das Geheimnis erscheint einmal in einem grünen Feld. Kopieren Sie es, bevor Sie die Seite verlassen — nichts zeigt es wieder an.
  • Jede Zeile des Webhooks trägt dann einen Send test ping-Button und einen Löschen-Link. Das Löschen stoppt die Lieferungen sofort.

Von der API — erstellen. Ihr API-Schlüssel ist der in Ihrem Konto, gesendet als X-Api-Key (oder ?key=).

curl -sS -X POST https://olud.ai/api/webhooks.php \
  -H "X-Api-Key: $OSAI_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "url": "https://your-app.example/osai-hook",
        "events": ["release", "health", "license"],
        "repos": ["acme/inference-server", "acme/tiny-router"],
        "format": "json"
      }'

Der Datenblock der Antwort. Jede Antwort enthält auch einen Meta-Block mit unserer Attribution. Das Geheimnis ist hier und sonst nirgendwo.

{
  "id": "whk_9b41c7e2f0a5d3861c4e",
  "url": "https://your-app.example/osai-hook",
  "events": ["release", "health", "license"],
  "repos": ["acme/inference-server", "acme/tiny-router"],
  "secret": "whs_7d2a19f4c6b03e58a1d7f492c0b6e35847ac91d2e6f0b8a3",
  "note": "Speichern Sie dieses Geheimnis jetzt — es wird nur einmal angezeigt. Überprüfen Sie jede Lieferung: X-OSAI-Signature == \"sha256=\" + HMAC_SHA256(raw_body, secret). Testen Sie es: POST {\"ping\":\"whk_9b41c7e2f0a5d3861c4e\"}."
}

Was die URL erfüllen muss

  • Schema https. http wird abgelehnt.
  • Ein Host muss vorhanden sein.
  • Wenn Sie einen Port angeben, muss er 443 sein. https://your-app.example:8443/hook wird abgelehnt.
  • Der Host kann nicht localhost sein und darf nicht mit .local oder .internal enden.
  • Wir lösen den Host auf. Wenn eine Adresse, die zurückgegeben wird, in einem privaten oder reservierten Bereich liegt, wird die URL abgelehnt.
  • Wir rufen Ihren Endpunkt während der Erstellung nicht auf. Ein Host, der nicht aufgelöst werden kann, besteht diesen Test und schlägt später bei der Lieferung fehl. Senden Sie einen Test-Ping, um es herauszufinden.
  • Eine schlechte URL antwortet mit 400 bad_url.

Was Repos akzeptiert

  • Der Standardwert ist ["*"] — jedes Repository, das wir verfolgen.
  • Einträge werden beschnitten und in Kleinbuchstaben umgewandelt, sodass die Übereinstimmung nicht groß-/kleinschreibungssensitiv ist.
  • Ein Eintrag muss wie owner/name aussehen: owner beginnt mit einem Buchstaben oder einer Ziffer, gefolgt von Buchstaben, Ziffern, Punkt, Unterstrich, Bindestrich.
  • Einträge, die nicht übereinstimmen, werden ohne ein Wort verworfen. Wenn nichts übrig bleibt, erhalten Sie 400 bad_repos.
  • "*" überall in der Liste ersetzt die gesamte Liste. ["acme/one", "*"] wird als ["*"] gespeichert.
  • Mehr als 100 Einträge antworten mit 400 too_many_repos. Verwenden Sie "*" ab diesem Punkt.

Die vier Ereignisse

Jedes Ereignis trägt ein Repository. Ein Ereignis ist ein POST — Ereignisse werden niemals zusammengefasst. Der Name befindet sich im X-OSAI-Event-Header und im Ereignisfeld des Körpers.

EreignisWird ausgelöst, wennSchlüssel innerhalb der Daten
Gesundheitdas Gesundheitslabel eines Repositories sich ändertvon, zu, Sterne, Seite
Veröffentlichungein neuer Release-Tag für ein Repository erscheintTag, Name, URL
Lizenzdie Lizenz, die wir für ein Repository halten, sich ändertvon, zu
neues_projektein Repository betritt das VerzeichnisSterne, Seite

Gesundheit

{
  "webhook_id": "whk_9b41c7e2f0a5d3861c4e",
  "event": "health",
  "repo": "acme/inference-server",
  "data": {
    "from": "Gedeihend",
    "to": "Verlangsamt",
    "stars": 58120,
    "page": "https://olud.ai/project/acme-inference-server.html"
  },
  "sent_at": "2026-07-27T05:41:12+00:00"
}

von und zu sind Labels, keine Zahlen. Die sechs Labels, die wir veröffentlichen: Gedeihend, Gesund, Wartungsfähig, Verlangsamt, Gefährdet, Archiviert. Sterne ist die Anzahl der Sterne, die wir für das Repository halten. Kein Ereignis wird ausgelöst, wenn ein Repository zum ersten Mal ein Label erhält — eine Änderung benötigt einen vorherigen Wert zum Vergleichen.

Veröffentlichung

{
  "webhook_id": "whk_9b41c7e2f0a5d3861c4e",
  "event": "release",
  "repo": "acme/inference-server",
  "data": {
    "tag": "v0.6.2",
    "name": "Acme Inference Server",
    "url": "https://github.com/acme/inference-server/releases"
  },
  "sent_at": "2026-07-27T05:41:12+00:00"
}

Tag ist der Git-Tag. Name ist der Anzeigename des Projekts in unserem Verzeichnis, nicht der Titel des Releases. URL verweist immer auf die Releases-Seite des Repositories, niemals auf ein spezifisches Release — baue die Tag-URL selbst, wenn du sie benötigst.

Lizenz

von und zu sind die Lizenzstrings, die wir halten. Dieses Ereignis hat keinen Seiten-Schlüssel.

{
  "webhook_id": "whk_9b41c7e2f0a5d3861c4e",
  "event": "license",
  "repo": "acme/inference-server",
  "data": {
    "from": "Apache-2.0",
    "to": "BSL-1.1"
  },
  "sent_at": "2026-07-27T05:41:12+00:00"
}

neues_projekt

{
  "webhook_id": "whk_9b41c7e2f0a5d3861c4e",
  "event": "new_project",
  "repo": "acme/tiny-router",
  "data": {
    "stars": 1840,
    "page": "https://olud.ai/project/acme-tiny-router.html"
  },
  "sent_at": "2026-07-27T05:41:12+00:00"
}

Höchstens 25 new_project-Ereignisse pro Durchlauf, höchste Sternzahlen zuerst. Bei einem ersten Durchlauf oder wenn mehr als 200 Repositories gleichzeitig erscheinen, werden sie aufgezeichnet und keine werden gesendet — dieser Schutz verhindert, dass ein erneutes Importieren dich überflutet.

Body und Header

Im Format JSON hat der Body fünf Schlüssel, in dieser Reihenfolge. Nichts anderes wird hinzugefügt.

{
  "webhook_id": "whk_9b41c7e2f0a5d3861c4e",
  "event": "release",
  "repo": "acme/inference-server",
  "data": { },
  "sent_at": "2026-07-27T05:41:12+00:00"
}

webhook_id ist die ID, die du erstellt hast: whk_ plus 20 hexadezimale Zeichen. repo ist der Kleinbuchstaben-Besitzer/Name und ist nur bei einem Test-Ping null. data ist ein Objekt, das leer ist für ein Ereignis, das keine Felder trägt. sent_at ist UTC, ISO 8601 mit einem Offset.

HeaderWert
Content-Typeapplication/json
User-Agentolud.ai-Webhooks/1.0
X-OSAI-Eventhealth, release, license, new_project oder ping
X-OSAI-Delivery16 hexadezimale Zeichen, frisch für jeden POST
X-OSAI-Signaturesha256= gefolgt von der HMAC-SHA256 des Bodys

Diese fünf sind das gesamte Set. X-OSAI-Delivery wird nicht auf unserer Seite gespeichert — verwende es, um ein Duplikat in deinem eigenen Protokoll zu erkennen.

Ein Test-Ping, gesendet durch POST {"ping":"whk_…"}. Dieselben Header, dieselbe Signatur, X-OSAI-Event: ping.

{
  "webhook_id": "whk_9b41c7e2f0a5d3861c4e",
  "event": "ping",
  "repo": null,
  "data": {
    "message": "Es funktioniert. Echte Ereignisse kommen nach jedem Morgenscan an."
  },
  "sent_at": "2026-07-27T05:41:12+00:00"
}
Antworte 2xx und antworte schnell. Wir warten 6 Sekunden, dann zählen wir einen Fehler. Überprüfe die Signatur, schiebe das Ereignis in eine Warteschlange, gib 200 zurück und erledige die Arbeit danach.

Die Signatur überprüfen

Berechne die HMAC-SHA256 des rohen Bodys mit deinem Geheimnis neu, präge es mit sha256= vor und vergleiche es mit X-OSAI-Signature. Das Geheimnis ist der whs_ String aus der Erstellungsantwort: whs_ plus 48 hexadezimale Zeichen.

PHP

<?php
$raw    = file_get_contents('php://input');   // rohe Bytes, vor jeder Analyse
$sent   = $_SERVER['HTTP_X_OSAI_SIGNATURE'] ?? '';
$expect = 'sha256=' . hash_hmac('sha256', $raw, $SECRET);

if (!hash_equals($expect, $sent)) {           // konstante Zeit
    http_response_code(401);
    exit;
}

$event = json_decode($raw, true);             // nur nach der Überprüfung parsen
http_response_code(200);

Node, mit Express

const crypto  = require('crypto');
const express = require('express');
const app = express();

// express.raw behält die Bytes. express.json() würde sie zerstören.
app.post('/osai-hook', express.raw({ type: 'application/json' }), (req, res) => {
  const sent   = req.get('X-OSAI-Signature') || '';
  const expect = 'sha256=' + crypto.createHmac('sha256', SECRET)
                                   .update(req.body).digest('hex');

  // timingSafeEqual wirft einen RangeError bei Puffern unterschiedlicher Länge,
  // also überprüfe zuerst die Länge und vergleiche dann in konstanter Zeit.
  const a = Buffer.from(sent), b = Buffer.from(expect);
  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.sendStatus(401);
  }

  const event = JSON.parse(req.body.toString('utf8'));
  res.sendStatus(200);
});

Python, mit Flask

import hmac, hashlib, json
from flask import Flask, request, abort

app = Flask(__name__)

@app.post("/osai-hook")
def osai_hook():
    raw    = request.get_data()               # Bytes, vor jeder Analyse
    expect = "sha256=" + hmac.new(SECRET.encode(), raw, hashlib.sha256).hexdigest()
    sent   = request.headers.get("X-OSAI-Signature", "")

    if not hmac.compare_digest(expect, sent):  # konstante Zeit
        abort(401)

    event = json.loads(raw)
    return "", 200

Vergleichen Sie mit hash_equals, crypto.timingSafeEqual oder hmac.compare_digest. Niemals mit == oder ===. Ein einfacher String-Vergleich stoppt beim ersten Byte, das sich unterscheidet, sodass die benötigte Zeit einem Angreifer verrät, wie viele führende Bytes sie richtig haben. Wiederholen Sie die Messung und sie rekonstruieren die Signatur Byte für Byte, um dann gefälschte Ereignisse zu posten. Die drei oben genannten Funktionen lesen jedes Byte, unabhängig von der Eingabe.

  • Hashen Sie die rohen Bytes, bevor Sie sie parsen. Ein Körper, den ein Framework geparst und neu serialisiert hat, wird zu etwas anderem gehasht, und jede Lieferung wird ungültig aussehen.
  • Das JSON-Format entkommt nicht-ASCII-Zeichen als \uXXXX. Eine erneute Serialisierung verliert das ebenfalls.
  • Ein fehlender Header kommt als leerer String an. Alle drei Beispiele lehnen ihn ab, anstatt abzustürzen.
  • Das Geheimnis wird einmal bei der Erstellung angezeigt. Wenn Sie es verlieren, löschen Sie den Webhook und erstellen Sie einen neuen — Sie erhalten eine neue ID und ein neues Geheimnis.
  • Halten Sie ein Geheimnis pro Webhook. Zwei Webhooks teilen sich niemals eines.
Slack und Discord ignorieren X-OSAI-Signature. Wir senden es trotzdem, und es deckt immer noch ab, was sie erhalten: die Signatur wird über die tatsächlich geposteten Bytes berechnet, unabhängig vom Format.

json, slack, discord

Das Format wird bei der Erstellung gewählt und standardmäßig auf JSON gesetzt. Es gibt keinen Update-Endpunkt: Um es zu ändern, löschen Sie den Webhook und erstellen Sie einen neuen. GET berichtet das Format jedes Webhooks; die Antwort bei der Erstellung gibt es nicht wieder. Ein Wert außerhalb der drei Antworten 400 bad_format.

FormatWas wir postenURL zum Einfügen
JSONDie obige Payload, unverändertIhr eigener Endpunkt
SlackText, plus einen mrkdwn-Abschnitt BlockEine Slack Incoming-Webhook-URL
DiscordEin Embed: Titel, URL, Beschreibung, Farbe, FußzeileEine Discord-Kanal-Webhook-URL

Slack

Ein Release-Ereignis, gepostet an Slack

{
  "text": "🚀 acme/inference-server veröffentlicht v0.6.2 — Acme Inference Server",
  "blocks": [
    {
      "type": "section",
      "text": {
        "type": "mrkdwn",
        "text": "🚀 *<https://github.com/acme/inference-server/releases|acme/inference-server veröffentlicht v0.6.2>*\nAcme Inference Server"
      }
    }
  ]
}

Holen Sie die URL von Slack: Fügen Sie eine App zum Arbeitsbereich hinzu, aktivieren Sie Incoming Webhooks, fügen Sie einen für den gewünschten Kanal hinzu, kopieren Sie die https://hooks.slack.com/services/… URL und fügen Sie sie in das URL-Feld ein. Text ist immer ausgefüllt — es ist das, was Slack in der Benachrichtigung und in Clients anzeigt, die keine Blöcke rendern.

Discord

Ein Lizenzereignis, gepostet an Discord

{
  "embeds": [
    {
      "title": "🔑 acme/inference-server hat die Lizenz geändert",
      "url": "https://github.com/acme/inference-server",
      "description": "Apache-2.0 → BSL-1.1",
      "color": 14427686,
      "footer": { "text": "olud.ai" }
    }
  ]
}

Holen Sie die URL von Discord: Kanaleinstellungen, Integrationen, Webhooks, Neuer Webhook, Webhook-URL kopieren — https://discord.com/api/webhooks/… — und fügen Sie sie in das URL-Feld ein. Farbe ist eine dezimale Ganzzahl: 14427686 (#DC2626) für Lizenz, 6514417 (#6366F1) für Release, new_project und ping.

Beide Hosts bestehen die URL-Prüfung. Wenn ein Lizenzereignis keine Seite hat, fällt der Link zurück auf https://github.com/owner/name; health und new_project verlinken zur Projektseite auf olud.ai; release verlinkt zur Releases-Seite des Repositories.

Bekannter Fehler, health nur auf Slack und Discord. Der Nachrichtenbauer liest von und zu als Zahlen, aber health trägt Labels. Der Titel erscheint als "acme/inference-server health 0 → 0", der Text liest immer "Wartung verbessert sich.", und die Farbe ist immer grün — auch wenn der Score sinkt. Das JSON-Format ist nicht betroffen: es leitet die beiden Labels so weiter, wie sie sind. Verwenden Sie JSON, wenn Sie die Health-Labels benötigen.

Lieferung, Fehler, Deaktivierung

Lieferungen laufen über den Alert-Pass, send-alerts.php — die gleiche Erkennung, die die Mitglieds-E-Mails produziert. Der Versand erfolgt direkt nach der Erkennung im selben Prozess. Es gibt keinen separaten Zeitplan und keine Warteschlange. Die API beschreibt die Frequenz als "täglich, nach dem morgendlichen Scan".

  • Ein POST pro Ereignis, pro passendem Webhook. Ein Webhook empfängt ein Ereignis, wenn der Ereignisname in seiner Ereignisliste steht und wenn das Repository in seiner Repos-Liste oder Repos ist ["*"].
  • Ein Erfolg ist HTTP 200 bis 299, innerhalb des 6-Sekunden-Timeouts. Ein 4xx, ein 5xx, ein Timeout, ein DNS- oder TLS-Fehler zählen alle als Fehler.
  • Ein Erfolg setzt fails auf 0 zurück und fügt 1 zu delivered hinzu.
  • Ein Fehler fügt 1 zu fails hinzu. Es gibt keinen Retry. Das Ereignis wird nicht erneut gesendet — die nächste Lieferung ist die nächste Änderung, die wir erkennen.
  • Bei 10 aufeinanderfolgenden Fehlern wird der Webhook deaktiviert, mit dem UTC-Zeitstempel dieses Moments versehen, und die verbleibenden Ereignisse dieser Ausführung werden für ihn übersprungen.
  • Ein deaktivierter Webhook bleibt in Ihrer Liste, als deaktiviert markiert. Es gibt keinen Aufruf, um ihn wieder zu aktivieren: Löschen Sie ihn und erstellen Sie einen neuen, mit einer neuen ID und einem neuen Geheimnis.

Den Status lesen

curl -sS https://olud.ai/api/webhooks.php -H "X-Api-Key: $OSAI_KEY"

Die Antwort, einschließlich Meta

{
  "ok": true,
  "data": [
    {
      "id": "whk_9b41c7e2f0a5d3861c4e",
      "url": "https://your-app.example/osai-hook",
      "events": ["release", "health"],
      "repos": ["*"],
      "format": "json",
      "created": "2026-07-20T09:14:02+00:00",
      "delivered": 37,
      "fails": 0,
      "disabled": null
    }
  ],
  "meta": {
    "plan": "dev",
    "used": 1,
    "limit": 3,
    "events": ["health", "release", "license", "new_project"],
    "formats": ["json", "slack", "discord"],
    "delivery": "täglich, nach dem morgendlichen Scan",
    "signature": "X-OSAI-Signature: sha256=HMAC_SHA256(body, secret)"
  }
}

delivered ist die Lebensdaueranzahl erfolgreicher POSTs. fails ist die aktuelle aufeinanderfolgende Serie, sodass sie beim nächsten Erfolg auf 0 zurückfällt. disabled ist null oder der Zeitstempel, zu dem wir gestoppt haben. Geheimnisse werden niemals von GET zurückgegeben.

Vier Möglichkeiten, wie Lieferungen stoppen

  • Ihr Endpunkt schlägt ständig fehl. Zehn Fehler hintereinander und der Webhook ist deaktiviert. Beheben Sie den Endpunkt, löschen Sie den Webhook, erstellen Sie einen neuen, pingen Sie ihn.
  • Ihr Plan wird auf kostenlos zurückgesetzt — eine Stornierung. Der Webhook bleibt erhalten und wird bei jeder Zustellung stillschweigend übersprungen. Ein erneuter Planwechsel weckt ihn wieder, dieselbe ID, dasselbe Geheimnis.
  • Sie rotieren Ihren API-Schlüssel in Ihrem Konto. Der alte Schlüssel verlässt den Schlüssel-Speicher, während der Webhook weiterhin darauf verweist: Er fällt aus Ihrer Liste, kann nicht mehr gepingt oder gelöscht werden, und jede Zustellung überspringt ihn wie einen kostenlosen Schlüssel. Löschen Sie Ihre Webhooks, bevor Sie den Schlüssel rotieren, und erstellen Sie sie dann erneut mit dem neuen.
  • Sie löschen ihn. Die Lieferungen stoppen sofort.

Testen ohne Warten

curl -sS -X POST https://olud.ai/api/webhooks.php \
  -H "X-Api-Key: $OSAI_KEY" -H "Content-Type: application/json" \
  -d '{"ping":"whk_9b41c7e2f0a5d3861c4e"}'

Beide Ergebnisse

HTTP/1.1 200
{"ok":true,"data":{"ping":"delivered","http":200}}

HTTP/1.1 502
{"ok":false,"error":{"code":"ping_failed",
  "message":"Ihr Endpunkt antwortete mit HTTP 500 — ein 2xx wird erwartet."}}

Der Ping wird im Format des Webhooks gesendet, auf die gleiche Weise signiert, mit Ereignis-Ping und Repo null. Er bewegt sich weder als geliefert noch schlägt er fehl, sodass ein fehlgeschlagener Ping Sie niemals in Richtung der Deaktivierungsschwelle drängt. Es funktioniert auch in einem kostenlosen Plan, wenn der Webhook bereits existiert, während geplante Lieferungen nicht funktionieren.

HTTP 0 in einer ping_failed-Nachricht bedeutet, dass wir überhaupt keine Antwort erhalten haben: Der Host konnte nicht aufgelöst werden, TLS wurde nicht abgeschlossen oder die 6 Sekunden sind abgelaufen.

Fehlercodes

Jeder Fehler kommt in derselben Form zurück, mit einem passenden HTTP-Status.

{
  "ok": false,
  "error": {
    "code": "bad_url",
    "message": "URL muss https, öffentlich erreichbar, Standardport (kein localhost oder private Bereiche) sein."
  }
}
HTTPcodeWann
400bad_jsonDer Körper ist kein JSON-Objekt.
400bad_urlDie URL hat die Überprüfung nicht bestanden: nicht https, ein anderer Port als 443, localhost, .local, .internal oder eine Adresse in einem privaten oder reservierten Bereich.
400bad_eventsNach der Filterung enthielten die Ereignisse keine von health, release, license, new_project.
400bad_reposKein Eintrag war "*" oder ein gültiger Besitzer/Name.
400too_many_reposMehr als 100 Repositories bei einem Webhook.
400bad_formatFormat war nicht json, slack oder discord.
401missing_keyKein X-Api-Key-Header und kein ?key= Parameter.
403bad_keyDer Schlüssel ist nicht in unserem Schlüssel-Speicher. Ein rotierter oder widerrufener Schlüssel landet hier.
403paid_featureIhr Plan erlaubt 0 Webhooks.
404not_foundDie ID im Ping oder in ?id= ist nicht an Ihren Schlüssel angehängt.
405method_not_allowedEine Methode, die nicht GET, POST oder DELETE ist.
429limit_reachedSie haben bereits so viele Webhooks, wie Ihr Plan erlaubt.
500store_write_failedWir konnten die Änderung nicht auf die Festplatte schreiben. Versuchen Sie es erneut.
502ping_failedIhr Endpunkt antwortete auf den Test-Ping mit etwas anderem als einem 2xx.

Zwei praktische Punkte. Das Verwalten von Webhooks verbraucht nicht Ihr tägliches API-Anfragekontingent — dieser Endpunkt berührt nie den Zähler und sendet keine X-RateLimit-Header. Und DELETE fehlt in der CORS-Allow-Methods-Liste, sodass ein Cross-Origin-Aufruf von einem Browser bei der Vorabprüfung fehlschlägt; löschen Sie serverseitig oder von der Kontoseite, die dieselbe Herkunft hat.

Automatisierungen

n8n: lesen und empfangen

Zwei Knoten decken beide Richtungen ab. Ein HTTP Request-Knoten liest unsere Daten. Ein Webhook-Knoten empfängt unsere Ereignisse. Nichts aus der Community-Liste zu installieren.

Katalog lesen

Jeder Endpunkt antwortet mit GET unter https://olud.ai/api/v1, mit Ihrem Schlüssel im X-Api-Key-Header. /meta ist der eine Endpunkt, der ohne Schlüssel antwortet und Ihr Kontingent nicht berührt — verwenden Sie ihn als ersten Knoten, während Sie testen, da er die URL und den Netzwerkpfad überprüft, bevor Sie einen Aufruf tätigen.

Ereignisse empfangen

Fügen Sie einen Webhook-Knoten hinzu, Methode POST, und kopieren Sie seine Produktions-URL. Registrieren Sie diese URL in Ihrem Konto (Webhooks-Bereich) oder POSTen Sie sie an https://olud.ai/api/webhooks.php mit Ihrem Schlüssel. Vier Ereignisse zur Auswahl: release, health, license, new_project. Lieferungen erfolgen einmal täglich, in demselben Durchgang, der die E-Mail-Benachrichtigungen sendet — nicht in dem Moment, in dem etwas passiert.

Ein Lieferkörper, im Format json (das Standardformat):

Was in den Daten steht, hängt vom Ereignis ab:

  • release — tag, name, url (die Releases-Seite des Repositories)
  • health — from, to, stars, page
  • license — from, to
  • new_project — stars, page
  • ping — message (nur Testlieferungen)

Bei einem Gesundheitsereignis sind from und to Labels, keine Zahlen: Thriving (Punktzahl 85 und höher), Healthy (70+), Maintained (50+), Slowing down (30+), At risk (unter 30). Vergleichen Sie Text in Ihrem IF-Knoten, nicht Ganzzahlen.

Jede Lieferung trägt drei Header: X-OSAI-Event, X-OSAI-Delivery (eine eindeutige ID pro Lieferung, verwenden Sie sie, um Duplikate zu entfernen) und X-OSAI-Signature, in der Form sha256=<HMAC-SHA256 des Körpers mit Ihrem Webhook-Geheimnis>. Das HMAC deckt die genauen Bytes ab, die wir gesendet haben, also wenn Sie es verifizieren möchten, aktivieren Sie die raw-body-Option des Webhook-Knotens. Ein Körper, der geparst und erneut serialisiert wurde, stimmt niemals überein.

Fügen Sie dies auf der Leinwand ein. Die beiden Knoten sind absichtlich unverbunden — jeder ist sein eigener Ausgangspunkt:

Dann geben Sie Ihren Schlüssel in das Header-Feld des HTTP-Knotens ein und aktivieren Sie den Workflow — die Produktions-URL eines Webhook-Knotens hört nur zu, während der Workflow aktiv ist.

Wenn nichts ankommt

  • Die Registrierung der URL antwortet mit 400 bad_url: der Endpunkt muss https sein, auf Port 443, auf einem öffentlich auflösbaren Host. Ein selbst gehostetes n8n über http, auf localhost, auf einem *.local-Namen oder in einem privaten IP-Bereich wird abgelehnt.
  • Die Registrierung antwortet mit 403 paid_feature: Webhooks beginnen im Dev-Plan — 3 Endpunkte im Dev, 10 im Pro, 50 im Org. Ein kostenloser Schlüssel kann keinen erstellen.
  • Die Registrierung antwortet mit 429 limit_reached: Sie haben bereits so viele Webhooks, wie Ihr Plan erlaubt. Löschen Sie zuerst einen.
  • Warten Sie nicht bis morgen, um es herauszufinden: POST {"ping":"whk_…"} an /api/webhooks.php und das Testereignis verlässt sofort, in derselben Form wie ein echtes. Wenn Ihr Endpunkt nicht mit 2xx antwortet, erhalten Sie 502 ping_failed mit dem Code, den er zurückgegeben hat.
  • Zehn aufeinanderfolgende Nicht-2xx-Antworten deaktivieren den Webhook stillschweigend. Ein Erfolg setzt den Zähler zurück. Ein deaktivierter Webhook kommt nur zurück, indem er neu erstellt wird. Die Lieferzeitüberschreitung beträgt 6 Sekunden, sodass ein Knoten, der langsam antwortet, als Fehler zählt.
  • Der Webhook wurde erstellt, aber nichts wird geliefert und es gibt keine Fehler: Überprüfen Sie den Plan für den Schlüssel, der ihn besitzt. Wenn er auf Free zurückgefallen ist, werden die Lieferungen übersprungen, während der Endpunkt registriert bleibt.
  • Das Geheimnis wird einmal bei der Erstellung angezeigt. Es gibt keine Möglichkeit, es zurückzulesen — löschen und neu erstellen.

Zapier und Make

Die gleichen zwei Richtungen, derselbe Schlüssel, keine App, die in ihren Verzeichnissen gefunden werden kann.

Empfangen: den Hook abfangen

In Zapier: Webhooks von Zapier, Trigger Catch Hook. In Make: das Webhooks-Modul, benutzerdefinierter Webhook. Beide geben Ihnen eine https-URL auf ihrer eigenen Domain, die unseren Test besteht. Fügen Sie sie in Ihr Konto als Webhook-Endpunkt ein, wählen Sie Ihre Ereignisse aus und senden Sie sich dann einen Ping und bestätigen Sie, dass der Zap oder das Szenario ihn erhält, bevor Sie die Schritte dahinter erstellen.

Wenn Sie die X-OSAI-Signature verifizieren möchten, benötigen Sie den Rohkörper und die Header. In Zapier bedeutet das Catch Raw Hook anstelle von Catch Hook. In Make aktivieren Sie die Webhook-Einstellung, die die Anfrage-Header beibehält. Unsere Signatur ist ein HMAC über die genauen Bytes des Körpers, sodass ein Schritt, der das JSON parst, bevor Sie es sehen, den Vergleich unmöglich macht.

Lesen: ein HTTP-Schritt

Zapier's Webhooks GET-Aktion oder Makes HTTP-Modul. Ein Schritt, ein Header:

Ein Erfolg ist {"ok":true,"data":[…],"meta":{…}}. Ein Fehler ist {"ok":false,"error":{"code":"…","message":"…"}} mit einem passenden HTTP-Status. Testen Sie ok, bevor Sie Felder zuordnen: Ein Fehlerkörper hat überhaupt keine Daten, und eine Zuordnung, die data[0] bei einem Fehler liest, produziert stillschweigend leere Werte im Folgenden.

  • 401 missing_key — der Header ist nicht angekommen. Überprüfen Sie, ob der Schritt ihn bei jedem Aufruf sendet, nicht nur beim ersten.
  • 403 invalid_key — Schlüssel unbekannt oder widerrufen.
  • 429 quota_exceeded — tägliches Kontingent erreicht, setzt sich um 00:00 UTC zurück. Erfolgreiche Antworten tragen X-RateLimit-Limit und X-RateLimit-Remaining, sodass Sie es kommen sehen können.
  • 503 graph_unavailable — der Graph wird neu aufgebaut. Versuchen Sie es in einer Minute erneut; dies ist der eine Fehler, der einen automatischen Retry wert ist.
  • 403 pro_required — /history/{slug} ist nur für Pro und Org.
  • 404 not_found — kein solches Projekt oder Produkt. Die Nachricht enthält einen /search-Vorschlag, dem Sie folgen können.
Planen Sie dies nicht jede Minute. Der Graph wird einmal jeden Morgen neu aufgebaut, sodass stündlich bereits häufiger ist, als sich die Daten ändern. Antworten tragen ein ETag, das vom Erstellungsdatum abgeleitet ist, und eine wiederholte Anfrage erhält 304 Not Modified — aber der Schlüssel wird vor diesem Vergleich gezählt, sodass ein 304 dennoch einen Aufruf gegen Ihr tägliches Kontingent kostet.

GitHub Action: Abhängigkeitsüberwachung

Die Aktion liest die Abhängigkeitsmanifeste des ausgecheckten Repositories, fragt uns die Lizenz und den Wartungsbericht jeder Abhängigkeit an und postet einen Kommentar zur Pull-Anfrage, in dem aufgeführt ist, was eine Entscheidung benötigt. Es schreibt denselben Kommentar bei jedem Durchlauf um — es findet ihn wieder durch einen versteckten Marker — sodass eine lange Pull-Anfrage nicht mit Duplikaten überfüllt wird.

Der gesamte Workflow, mit jedem Eingabewert auf dem Standardwert. Nur der api-key ist erforderlich:

actions/checkout muss zuerst kommen: die Aktion liest Dateien aus dem Arbeitsverzeichnis, und nur im Root, es sei denn, Sie setzen Pfade.

EingabeStandardWas es tut
api-keyerforderlichGesendet als X-Api-Key. Eine Abfrage pro distinct dependency. Ein kostenloser Schlüssel funktioniert.
github-token${{ github.token }}Postet den Kommentar. Benötigt Pull-Requests: schreiben Sie im Job.
health-floor45Kennzeichnen Sie eine Abhängigkeit, die unter diesem Wert von 100 liegt. 0 schaltet die Gesundheitsprüfung aus und behält nur Lizenzen. Lesen Sie die bekannte Grenze unten.
lizenzenAGPL-3.0,BSL-1.1,SSPL-1.0,Elastic-2.0,BUSL-1.1,NOASSERTIONDurch Kommas getrennt, ohne Berücksichtigung der Groß- und Kleinschreibung mit der Lizenz, die wir halten. Das Setzen ersetzt die Liste, es wird nicht hinzugefügt.
fail-on-findingfalseFehler bei der Überprüfung anstelle von nur Kommentieren.
pfadeleerDurch Kommas getrennte Manifeste zum Lesen. Leer bedeutet: Suchen Sie nach den vier bekannten Namen im Root.

NOASSERTION ist absichtlich in der Standardliste: es ist das, was wir halten, wenn das Repository keine Lizenzdatei hat, die eine Maschine erkennen kann, was eine Entscheidung ist, die zu treffen ist, und kein Detail. Die Aktion gibt einen Output aus, findings — die Anzahl der gekennzeichneten Abhängigkeiten, die auch geschrieben werden, wenn sie 0 ist.

Was es liest

  • package.json — die Schlüssel von dependencies und devDependencies. peerDependencies und optionalDependencies werden nicht gelesen.
  • requirements.txt — ein Name pro Zeile, Kommentare entfernt, Zeilen, die mit - beginnen, werden verworfen. Also wird -r other-requirements.txt nicht befolgt und -e . wird ignoriert.
  • pyproject.toml — nur Schlüssel, deren Wert mit einem Anführungszeichen oder einer geschweiften Klammer beginnt, was dem Poetry-Stil entspricht: fastapi = "^0.110". Ein PEP 621 Block, dependencies = ["fastapi>=0.110"], ergibt überhaupt nichts.
  • go.mod — eingerückte Zeilen der Form name vX.

Pfade können irgendwo im Baum zeigen, zum Beispiel apps/api/requirements.txt, aber der Basisname der Datei muss einer dieser vier sein. Eine Datei namens requirements-dev.txt hat keinen Parser: sie wird ohne Nachricht übersprungen.

Standardmäßig schlägt es Ihre Überprüfung nicht fehl. fail-on-finding ist false, sodass ein Fund ein Kommentar ist, kein roter Build — eine Lizenzänderung ist eine Entscheidung, und eine Pipeline, die rot wird für etwas, das niemand in fünf Minuten beheben kann, lehrt das Team, durchzuklicken. Zwei Dinge schlagen den Job fehl: ein fehlender api-key, protokolliert als ::error::api-key ist erforderlich, und fail-on-finding: true mit mindestens einem Fund.

Wie es fehlschlägt

  • Kein Manifest im Root oder kein Checkout-Schritt: "Kein Abhängigkeitsmanifest gefunden — nichts zu überprüfen." findings ist 0 und der Job ist grün. Ein grüner Lauf bedeutet nicht einen sauberen Baum — lesen Sie diese Zeile.
  • Das Ereignis hat keinen Pull-Request, zum Beispiel bei einem Push: "Kein Pull-Request im Kontext — Kommentar übersprungen." Die Findings sind weiterhin im Protokoll.
  • pull-requests: schreiben fehlt: "Kommentar konnte nicht gepostet werden (HTTP 403)." Der Job bleibt grün und der Kommentar erscheint nie. Schauen Sie sich das Protokoll an, nicht den Pull-Request.
  • Tägliches API-Kontingent während des Laufs erreicht: ::warning::Tägliches API-Kontingent erreicht — teilweiser Lauf. Es hört auf, Dinge nachzuschlagen und kommentiert, was es geschafft hat zu lösen. Ein Aufruf pro distinct dependency, also verbrauchen 300 Abhängigkeiten 300 der 500 täglichen Aufrufe eines kostenlosen Schlüssels.
  • Ein Manifest, das nicht geparst werden kann: "⚠ <file> nicht lesbar (…) — übersprungen". Die anderen Manifeste laufen weiterhin.
  • Der zusammengesetzte Schritt führt node aus dem PATH aus und verwendet native fetch. GitHub-gehostete Runner haben bereits Node 20. Ein selbstgehosteter Runner benötigt actions/setup-node mit Node 20 oder höher.
  • lizenzen: '' mit health-floor: '0' erzeugt für immer null Findings. Diese Kombination schaltet beide Prüfungen aus.

Was der Action fehlt

Ein Paketname ist kein Repository-Name. Jeder Name wird durch /api/v1/search?q=<name>&limit=5 geleitet und die Aktion behält ein Ergebnis nur, wenn der Projektname gleich dem Paketnamen ist, ohne Berücksichtigung der Groß- und Kleinschreibung. Alles andere wird stillschweigend verworfen — keine Kommentarzeile, keine Warnung. Das Raten des nächsten Ergebnisses würde Alarm über das falsche Projekt auslösen, was schlimmer ist, als still zu bleiben, aber es bedeutet, dass die Überprüfung weniger als Ihren Abhängigkeitsbaum abdeckt.

  • Scoped npm-Pakete verlieren ihren Scope vor der Abfrage: @types/node wird als node gesucht, was mit einem nicht verwandten Repository dieses Namens übereinstimmen kann. Dies ist der eine Fall, in dem das falsche Projekt im Kommentar enden kann.
  • Go-Module behalten ihren Pfad: github.com/gin-gonic/gin wird zu gin-gonic/gin, was niemals einem Repository-Namen (gin) entspricht. go.mod-Abhängigkeiten lösen sich nicht auf.
  • Ein Paket, dessen Repository anders benannt ist — der häufige Fall in Python — löst niemals auf.
  • Nur die fünf besten Ergebnisse werden untersucht und nur die erste exakte Übereinstimmung wird verwendet. Wenn zwei Repositories denselben Namen haben, gewinnt das mit mehr Sternen.

Die Zeile, die im Protokoll gelesen werden muss, lautet: Resolved N von M Abhängigkeiten · K markiert. Wenn N weit unter M liegt, hat die Überprüfung nur einen Teil Ihres Baums betrachtet. Nichts im Kommentar der Pull-Anfrage sagt das aus.

Bekannte Grenze für den Gesundheitsboden. Die Aktion liest den Wartungswert als Objektfeld, während /api/v1/search die Gesundheit als einfache Zahl zurückgibt. Mit der heutigen API-Antwort kann die Gesundheitsprüfung nicht ausgelöst werden, egal welchen Boden Sie festlegen: die Lizenzliste ist es, die Ergebnisse liefert. Der vollständige Wert mit seinen vier Komponenten wird von /api/v1/project/{id} bereitgestellt, falls Sie ihn in der Zwischenzeit benötigen.

OpenAPI-Spezifikation

Eine Datei beschreibt die Lese-API: https://olud.ai/openapi.json. OpenAPI 3.0.3, ein Server (https://olud.ai/api/v1), neun GET-Operationen, ein Sicherheitskonzept — ein API-Schlüssel im X-Api-Key-Header. Sie schreiben keine Integration; Sie fügen eine Adresse ein.

  • /meta — Erstellungsdatum und Projektanzahl. Ohne Sicherheit deklariert: es ist die Gesundheitsprüfung.
  • /search — q erforderlich, Limit 1 bis 50, Standard 15.
  • /projects — lang, lizenz, vertikal, health_min 0 bis 100, sortieren nach stars|health|momentum|recent (Standard stars), Limit 1 bis 100 (Standard 25), Offset 0 bis 100000 (Standard 0).
  • /project/{id} — der vollständige zusammengeführte Datensatz, einschließlich Gesundheit mit ihren Komponenten.
  • /emerging — Limit 1 bis 100, Standard 25.
  • /alternatives/{product} — Open-Source-Alternativen zu einem kommerziellen Produkt.
  • /models — Anbieter, Stufe, Limit 1 bis 200 (Standard 50), Offset.
  • /hf — am häufigsten heruntergeladen und im Trend auf Hugging Face.
  • /history/{slug} — 90 Tage Sterne, Gesundheit und Momentum. Pro und Org.

Importieren Sie es

  • Custom GPT — Konfigurieren, dann Aktionen, dann Import von URL. Authentifizierung: API-Schlüssel, benutzerdefinierter Header, Name X-Api-Key.
  • Dify, Flowise, Open WebUI — fügen Sie ein Tool aus einem OpenAPI-Schema hinzu, fügen Sie die URL ein, wählen Sie die Operationen aus, die Sie freigeben möchten, fügen Sie denselben Header hinzu.
  • Postman, Insomnia — Importieren, dann Link. Sie erhalten die neun Anfragen, dokumentiert. Setzen Sie X-Api-Key einmal auf Sammlungsebene, damit jede Anfrage ihn erbt.
  • Code-Generatoren — jeder OpenAPI-Generator erzeugt einen typisierten Client, TypeScript, Python oder Go, nur aus dieser Datei.

Egal welches Tool, es gibt nur zwei Dinge einzustellen: die URL der Datei und den Schlüssel als Header mit dem Namen X-Api-Key. Wenn ein Import neun Operationen anzeigt, aber jeder Aufruf mit 401 antwortet, wird der Header nicht gesendet — das ist das erste, was zu überprüfen ist.

Kontingente gelten pro Schlüssel und pro Tag, zurückgesetzt um 00:00 UTC: 500 Anfragen im Free-Tarif, 5.000 im Dev-Tarif, 50.000 im Pro-Tarif, 500.000 im Org-Tarif. Sie werden separat vom MCP-Server gezählt, sodass ein Assistent, der Fragen in Ihrem Editor stellt, niemals in dieses Budget eingreift.

Webhook-Management ist nicht in dieser Datei. Es befindet sich unter https://olud.ai/api/webhooks.php mit demselben Schlüssel: GET listet Ihre Endpunkte mit ihren Zustell- und Fehlerzahlen auf, POST erstellt einen oder sendet einen Ping, DELETE entfernt einen. Ein Tool, das die Spezifikation importiert, kann keinen Webhook für Sie erstellen.

Vier RSS-Feeds

Kein Schlüssel, keine Anmeldung, kein Konto. feed.php akzeptiert genau vier Typen: Nachrichten, Blog, Releases, Emerging.

URLWas es trägtWoher es kommt
/feed.phpBis zu 30 neue Projekte (★Sterne · Eigentümer/Name), die neuen Modelle des Tages (Neues Modell: Name (Anbieter), mit dem Kontextfenster in der Beschreibung), neue Hugging Face Spaces (Neuer Space: Name des Autors, mit der Anzahl der Likes) und das Papier des Tages.today-data.json, stündlich neu aufgebaut
/feed.php?type=releasesBis zu 60 Versionen, die von den Projekten, die wir verfolgen, ausgeliefert werden: Titel Projekt + Tag, Link zur Veröffentlichung, guid Eigentümer/Name@Tag.releases-data.json, stündlich neu aufgebaut
/feed.php?type=emergingBis zu 40 aufstrebende Projekte — gesund, beschleunigend, noch wenig bekannt. Beschreibung: ★Sterne · Gesundheit N/100 · +N Sterne diese Woche.das Diagramm, jeden Morgen neu aufgebaut
/feed.php?type=blogArtikel unter /blog/<slug>/, /blog/alternatives/ und /reports/. Titel und Beschreibung sind der eigene Titel und die Meta-Beschreibung der Seite; das Datum ist die Änderungszeit der Datei.von der Festplatte lesen, sodass ein neuer Artikel von selbst erscheint

Alle vier antworten mit RSS 2.0 als application/rss+xml, in Englisch, neuester Artikel zuerst, mit Cache-Control: public, max-age=1800. Das sind 30 Minuten: Ein Leser, der häufiger abfragt, erhält die zwischengespeicherte Kopie, die dieselbe Antwort schneller liefert.

Guids sind stabil und nicht immer der Link, was Sie beim Duplizieren in einer Automatisierung wollen: Releases verwenden owner/name@tag, aufstrebende Projekte verwenden emerging:<id>, das Papier des Tages verwendet seine URL plus das Datum, alles andere verwendet seinen Link.

Die Falle: ein unbekannter Typ ist kein Fehler. ?type=release im Singular oder ein Tippfehler gibt den Nachrichten-Feed mit HTTP 200 zurück. Wenn zwei Ihrer Feeds verdächtig identisch aussehen, überprüfen Sie die Schreibweise von type. Werte werden beschnitten und in Kleinbuchstaben umgewandelt, sodass ?type=Releases in Ordnung ist.

Richten Sie Slack, Teams oder Feedly auf sie aus, um zu lesen, oder verwenden Sie den RSS-Trigger in n8n, Zapier und Make, wenn ein Zeitplan besser zu Ihnen passt als ein Webhook — das ist auch der Weg, um Releases ohne einen kostenpflichtigen Plan zu erhalten. Wenn eine Quelldatei nicht neu erstellt wurde, antwortet der Feed weiterhin mit 200 und einem leeren Kanal anstelle eines Fehlers, sodass eine Automatisierung, die plötzlich nichts erhält, nicht unbedingt defekt ist.