Created bymario-alka.dePowered bygodcore.denoob2claw.detricoma.de
REST API v1

LLM Benchmark API

Modelle, Hardware und Hersteller abrufen und pflegen – sowie Performance- und Harness-Ergebnisse strukturiert hochladen. Diese Doku ist so geschrieben, dass sie auch von KI-Agents direkt umgesetzt werden kann.

Vorabphase

Die Schnittstelle ist stabil, Tokens werden derzeit auf Anfrage vergeben. Endpunkte und Felder koennen sich bis zur offiziellen Freigabe noch leicht aendern.

Schnellstart

Basis-URL: https://llm-benchmark.de/api/v1. Alle Antworten sind JSON und liegen unter dem Schluessel data. Lesen (GET) ist oeffentlich; Schreiben braucht ein Bearer-Token.

# 1) Rechte pruefen
curl -H "Authorization: Bearer DEIN_TOKEN" https://llm-benchmark.de/api/v1/me

# 2) Modell/Hardware finden
curl "https://llm-benchmark.de/api/v1/match?resource=gpus&name=RTX%205090"

# 3) Ergebnis senden
curl -X POST https://llm-benchmark.de/api/v1/results \
     -H "Authorization: Bearer DEIN_TOKEN" -H "Content-Type: application/json" \
     -d '{ "model_slug":"qwen3-32b","gpu_slug":"geforce-rtx-5090","gpu_count":1,
           "cpu_slug":"epyc-9654","cpu_count":1,"ram_gb":256,
           "benchmark_type":"performance","model_server_type":"vllm",
           "prefill_tokens_s":2450.7,"generation_tokens_s":184.3,
           "ttft_ms":126.4,"duration_ms":60000,"concurrency":8 }'

Konventionen

  • Format: Anfragen mit Body senden Content-Type: application/json. Antworten sind JSON mit Nutzdaten unter data bzw. einer Fehlermeldung unter error.
  • Slugs: Jeder Katalog-Eintrag (Modell, GPU, CPU, Mainboard, Hersteller) hat einen eindeutigen slug (Kleinbuchstaben, Ziffern, Bindestriche). Ergebnisse verweisen ueber Slugs auf den Katalog.
  • Idempotenz: Ein erneuter Ergebnis-Upload mit gleichem Modell + Hardwareprofil + Typ + measured_at wird serverseitig dedupliziert (Antwort enthaelt dann "deduped": true).
  • Token-Sicherheit: Der Token gehoert ausschliesslich in den Authorization-Header, niemals in die URL. Gespeichert wird nur sein SHA-256-Hash.

Authentifizierung

GET-Abfragen auf den Katalog und die Ergebnisliste sind oeffentlich. POST, PUT, DELETE sowie /me und /aliases erfordern ein Bearer-Token.

Authorization: Bearer DEIN_TOKEN
Content-Type: application/json

Rechte & Rollen

Was ein Token darf, ergibt sich aus Scopes (am Token) und der Rolle (am Benutzer). Fuer Agents entscheidend ist die abgeleitete Faehigkeit can_create – sie steuert, ob unbekannte Hardware/Modelle selbst angelegt werden duerfen oder zugeordnet werden muessen.

RolleLesenErgebnisse sendenZuordnen (Alternativname)Katalog anlegen/aendern
viewerja
contributorjajaja
contributor_api („Contributor + API Full Access“)jajajaja
adminjajajaja

Scopes am Token: read (lesen), write (Ergebnisse senden + zuordnen), create (Katalog anlegen). Ein Token darf anlegen, wenn es den Scope create ODER die Rolle admin/contributor_api besitzt.

Loeschen (DELETE) von Katalog-Eintraegen (Modelle, Hersteller, Grafikkarten, CPUs, Mainboards) ist ausschliesslich Admins vorbehalten – unabhaengig vom create-Recht. Alle anderen Rollen erhalten dabei 403.

Merke fuer Agents: Zuerst GET /me abfragen und nach capabilities.can_create verzweigen. Ist es false, darfst du NUR zuordnen (/aliases) – kein Anlegen.

Wer bin ich – GET /me

Gibt Benutzer, Rolle, Scopes und die abgeleiteten Faehigkeiten zurueck.

GET /api/v1/me
{
  "data": {
    "user_ID": 4,
    "display_name": "Marcel Sommer",
    "role": "contributor_api",
    "scopes": "read,write",
    "capabilities": {
      "can_read":  true,
      "can_write": true,
      "can_create": true,
      "can_match": true
    }
  }
}

Zuordnung / Aufloesung (wie Slugs gefunden werden)

Beim Senden eines Ergebnisses werden model_slug, gpu_slug, cpu_slug und optional board_slug serverseitig aufgeloest – in zwei Stufen:

  1. Exakter Slug. Gibt es einen aktiven Eintrag mit genau diesem Slug, wird er genommen.
  2. Normalisierter Vergleich. Sonst wird gross/klein und alle Sonderzeichen ignoriert und gegen Slug, Name und alle Alternativnamen verglichen. So matchen RTX-5090, rtx_5090, RTX 5090 automatisch auf denselben Eintrag.

Echte Namensunterschiede (anderer Suffix, Kurzform, interner Codename) matchen NICHT automatisch. Dafuer gibt es zwei Wege – siehe naechster Abschnitt.

Upload-Ablauf (fuer Agents)

Empfohlener, robuster Ablauf pro Ergebnis. Er deckt beide Rechte-Situationen ab:

1. GET /me                      -> canCreate = capabilities.can_create

2. Fuer JEDES Modell / GPU / CPU / (Mainboard):
   GET /match?resource=&name=   -> exact vorhanden?
     JA  -> nimm exact.slug
     NEIN:
        (b) canCreate == true   -> POST /<resource>   (SELBST ANLEGEN)
        (a) canCreate == false  -> waehle besten Kandidaten aus candidates[]
                                   POST /aliases          (ZUORDNEN)
                                   -> danach matcht der Name dauerhaft
           (kein passender Kandidat? -> abbrechen, Eintrag muss
            von einem create-berechtigten Nutzer angelegt werden)

3. POST /results  mit den aufgeloesten Slugs

Weg (a) „zuordnen“ gilt fuer Tokens ohne Anlage-Recht: der lokale Name wird per /aliases als Alternativname an einen VORHANDENEN Eintrag gehaengt. Weg (b) „anlegen“ gilt fuer Tokens mit can_create: fehlende Hardware/Modelle werden per POST selbst angelegt. Das Beispiel-Script unten macht genau diese Verzweigung automatisch.

Beispiel-Script zum Herunterladen

Eigenstaendiges PHP-Script (PHP 7.4+, cURL), das den kompletten Ablauf umsetzt – inkl. automatischer Verzweigung zwischen zuordnen und anlegen je nach Recht. Herunterladen, $API/$TOKEN setzen, Werte anpassen, ausfuehren.

⇩ upload-benchmark.php herunterladen

# Ausfuehren
php upload-benchmark.php

Hersteller

GET    /api/v1/manufacturers
GET    /api/v1/manufacturers/qwen
POST   /api/v1/manufacturers          # Anlege-Recht noetig
PUT    /api/v1/manufacturers/qwen     # Anlege-Recht noetig
DELETE /api/v1/manufacturers/qwen     # NUR Admin
{
  "slug": "qwen",
  "name": "Qwen (Alibaba)",
  "description": "Qwen-Modellfamilie von Alibaba.",
  "huggingface_url": "https://huggingface.co/Qwen",
  "website_url": "https://qwen.ai"
}

Modelle

GET    /api/v1/models
GET    /api/v1/models/qwen3-32b
GET    /api/v1/models?manufacturer=qwen
POST   /api/v1/models                 # Anlege-Recht noetig
PUT    /api/v1/models/qwen3-32b       # Anlege-Recht noetig
DELETE /api/v1/models/qwen3-32b       # NUR Admin
{
  "slug": "qwen3-32b",
  "manufacturer_slug": "qwen",
  "name": "Qwen3 32B",
  "parameter_count": "32B",
  "architecture": "Dense",
  "license_name": "Apache 2.0",
  "model_url": "https://huggingface.co/Qwen/Qwen3-32B"
}

manufacturer_slug muss auf einen vorhandenen Hersteller zeigen (sonst 422). Beim Anlegen prueft die API auf moegliche Dubletten (409) – mit "force": true laesst sich das uebergehen.

Grafikkarten

GET    /api/v1/gpus
GET    /api/v1/gpus/geforce-rtx-5090
POST   /api/v1/gpus                   # Anlege-Recht noetig
PUT    /api/v1/gpus/geforce-rtx-5090  # Anlege-Recht noetig
DELETE /api/v1/gpus/geforce-rtx-5090  # NUR Admin
{
  "slug": "geforce-rtx-5090",
  "vendor": "NVIDIA",
  "name": "GeForce RTX 5090",
  "memory_gb": 32,
  "idle_watt": 30,
  "max_watt": 575
}

CPUs

GET    /api/v1/cpus
GET    /api/v1/cpus/epyc-9654
POST   /api/v1/cpus                   # Anlege-Recht noetig
PUT    /api/v1/cpus/epyc-9654         # Anlege-Recht noetig
DELETE /api/v1/cpus/epyc-9654         # NUR Admin
{
  "slug": "epyc-9654",
  "vendor": "AMD",
  "name": "AMD EPYC 9654",
  "cores": 96,
  "threads": 192
}

Mainboards

GET    /api/v1/mainboards
GET    /api/v1/mainboards/asus-rog-x670e
POST   /api/v1/mainboards            # Anlege-Recht noetig
PUT    /api/v1/mainboards/asus-rog-x670e
DELETE /api/v1/mainboards/asus-rog-x670e  # NUR Admin
{
  "slug": "asus-rog-x670e",
  "vendor": "ASUS",
  "name": "ASUS ROG X670E"
}

Vorschlaege – GET /match

Liefert zu einem Namen den exakten Treffer (falls vorhanden) und die aehnlichsten Kandidaten (Score 0–100). Braucht nur Lese-Recht. Ideal, um vor dem Upload zu pruefen, ob ein Eintrag existiert, und um beim Zuordnen den richtigen Ziel-Slug zu waehlen.

GET /api/v1/match?resource=gpus&name=RTX%205090
{
  "data": {
    "exact": { "slug": "geforce-rtx-5090", "name": "GeForce RTX 5090" },
    "candidates": [
      { "slug": "geforce-rtx-5090", "name": "GeForce RTX 5090", "score": 100 },
      { "slug": "geforce-rtx-5080", "name": "GeForce RTX 5080", "score": 88.9 }
    ]
  }
}

resource = models | manufacturers | gpus | cpus | mainboards. Ist exact gleich null, gibt es keinen sicheren Treffer – dann anlegen (mit Recht) oder zuordnen.

Zuordnen – POST /aliases

Haengt einen Alternativnamen an einen bestehenden Katalog-Eintrag. Damit matchen abweichende Schreibweisen kuenftig automatisch. Braucht nur write-Recht (kein Anlege-Recht) – das ist der Weg fuer Tokens ohne can_create.

POST /api/v1/aliases
{
  "resource": "gpus",
  "slug": "geforce-rtx-5090",
  "alias": "NVIDIA RTX5090 32G"
}

Antwort enthaelt die aktualisierten alt_names. Zeigt der Alias bereits auf einen ANDEREN Eintrag, antwortet die API mit 409 (Konflikt) und nennt den betroffenen Slug.

Performance-Benchmark senden

GPU und CPU werden per Slug zugeordnet; Anzahl und RAM bilden automatisch ein wiederverwendbares Hardwareprofil. Die Antwort liefert ID, Slug und Status.

POST /api/v1/results
{
  "model_slug": "qwen3-32b",
  "gpu_slug": "geforce-rtx-5090",
  "gpu_count": 2,
  "gpu_used": 1,
  "cpu_slug": "epyc-9654",
  "cpu_count": 1,
  "ram_gb": 256,
  "board_slug": "asus-rog-x670e",
  "benchmark_type": "performance",
  "model_server_type": "vllm",
  "runtime_version": "0.10.0",
  "engine": "vllm",
  "quantization": "FP8",
  "start_path": "/opt/bin/start-vllm-qwen.sh",
  "context_length": 32768,
  "configuration_parameters": {
    "model": "Qwen/Qwen3-32B",
    "tensor_parallel_size": 2,
    "gpu_memory_utilization": 0.92,
    "max_model_len": 32768
  },
  "concurrency": 8,
  "prefill_tokens_s": 2450.7,
  "generation_tokens_s": 184.3,
  "ttft_ms": 126.4,
  "duration_ms": 60000,
  "notes": "Oeffentlicher Hinweis zu diesem Lauf (erscheint auf der Ergebnis-Detailseite)",
  "measured_at": "2026-07-31 10:00:00"
}

Antwort:

{
  "data": { "ID": 123, "slug": "run-20260731-100000-a1b2c3", "status": "published" }
}

Pflichtfelder: model_slug, gpu_slug, cpu_slug, ram_gb, benchmark_type, model_server_type (Alias runtime) sowie prefill_tokens_s, generation_tokens_s, duration_ms, concurrency. Ohne GPU (CPU-only) "gpu_slug":"none","gpu_count":0 senden. Optional: gpu_used = Anzahl der fuer diesen Lauf tatsaechlich genutzten GPUs (z.B. 1, wenn nur eine von gpu_count verbauten Karten verwendet wurde); wird auf der Detailseite als „nur M von N genutzt“ angezeigt.

Harness-Benchmark senden

POST /api/v1/results
{
  "model_slug": "qwen3-32b",
  "gpu_slug": "geforce-rtx-5090",
  "gpu_count": 2,
  "gpu_used": 1,
  "cpu_slug": "epyc-9654",
  "cpu_count": 1,
  "ram_gb": 256,
  "benchmark_type": "harness",
  "model_server_type": "llamacpp",
  "runtime_version": "b6200",
  "start_path": "/opt/bin/start-llamacpp.sh",
  "configuration_parameters": {
    "model": "/models/qwen3.gguf",
    "gpu_layers": 99,
    "context_size": 32768,
    "threads": 16
  },
  "points_achieved": 87,
  "points_max": 100,
  "duration_ms": 325000,
  "tasks": [
    {"name":"Recherche","success":true,"points":20,"points_max":20,"duration_ms":42000},
    {"name":"Codeaenderung","success":true,"points":30,"points_max":30,"duration_ms":81000}
  ]
}

Pflichtfelder Harness: zusaetzlich points_achieved, points_max, duration_ms, tasks. model_server_type ist der Modellserver (z.B. vllm, llamacpp), start_path der Startpfad, configuration_parameters die tatsaechlichen Start-/Modellparameter als JSON.

Ergebnisse abrufen, aktualisieren, filtern

GET    /api/v1/results/123
GET    /api/v1/results/run-20260731-100000-a1b2c3
GET    /api/v1/results?search=qwen
PUT    /api/v1/results/123            # eigene Benchmarks; Admin: alle
DELETE /api/v1/results/123            # blendet den Datensatz aus
GET /api/v1/results?type=performance
GET /api/v1/results?manufacturer=qwen
GET /api/v1/results?model=qwen3-32b
GET /api/v1/results?gpu=GeForce%20RTX%205090
GET /api/v1/results?cpu=EPYC%209654
GET /api/v1/results?ram=256
GET /api/v1/results?engine=vllm
GET /api/v1/results?mine=1            # nur eigene (Token noetig)

Bei PUT denselben vollstaendigen JSON-Aufbau wie beim Anlegen senden. Ein Benutzer darf eigene Benchmarks verwalten, der Admin alle.

Fehlercodes

CodeBedeutungWas tun
200 / 201OK / angelegt
401Token fehlt oder ungueltigBearer-Token pruefen
403 need:createAnlegen ohne Anlage-Recht versuchtStattdessen zuordnen (/aliases) oder Token mit create nutzen
403 need:adminLoeschen (DELETE) ohne Admin-RolleNur ein Admin darf Katalog-Eintraege loeschen
404Eintrag nicht gefundenSlug pruefen
409Dublette / Alias-KonfliktVorhandenen Slug verwenden bzw. "force":true
422Pflichtfeld fehlt / Slug „unbekannt“Fehlendes Feld ergaenzen bzw. Modell/GPU/CPU zuordnen oder anlegen