xenori

Für Entwickler · getestete Beispiele · EU-souverän

Die Xenori-API.

Starten Sie vollständige Agenten-Sessions per HTTP: Aufgabe senden, Fortschritt verfolgen, Ergebnis samt Dateien abholen. Dieselbe Plattform wie im Produkt — inklusive Sandbox, Skills und Verifikation.

Authentifizierung

Jede Anfrage trägt Ihren API-Schlüssel im Header x-maxicore-api-key. Schlüssel erstellen und widerrufen Sie im Produkt unter Einstellungen → Entwickler. Der Klartext wird genau einmal angezeigt; ein Widerruf wirkt sofort (die nächste Anfrage erhält 401). Verwenden Sie Schlüssel nur server-seitig — nie im Browser, nie im Client-Code, nie im Repository.

Session starten

curl -X POST https://xenori.ai/api/v2/task.create \
  -H "x-maxicore-api-key: $XENORI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "message": { "content": [ { "type": "text",
      "text": "Erstelle einen Monats-Haushaltsplan als Excel-Datei." } ] },
    "model": "max-smart"
  }'

# Antwort (getestet):
# { "ok": true, "request_id": "req_…",
#   "task": { "id": "task_6d09c5…", "status": "running", … } }

Die Stufe wählen Sie mit model: max-fast, max-smart oder max-genius. Government & Legal steht ausschließlich freigeschalteten Konten offen — fordert ein anderes Konto diese Stufe an, begrenzt der Server die Anfrage automatisch auf die Stufe des Kontos. Danach: Status abfragen, bis die Session terminal ist.

curl "https://xenori.ai/api/v2/task.detail?task_id=task_6d09c5…" \
  -H "x-maxicore-api-key: $XENORI_API_KEY"
# → "status": "running" | "in_queue" | "waiting" | "completed" | "failed" | "stopped"

Endpunkte

MethodePfadZweck
POST/api/v2/task.createNeue Aufgaben-Session starten (Text + optional Stufe/Anhänge)
GET/api/v2/task.detail?task_id=…Status & Metadaten einer Session
GET/api/v2/task.listMessages?task_id=…Vollständiger Verlauf (Nachrichten, Werkzeuge, Anhänge)
POST/api/v2/task.sendMessageFolge-Nachricht — steuert einen laufenden Lauf oder startet den nächsten Turn
POST/api/v2/task.stopLaufende Session anhalten
GET/api/v2/task.list?limit=…Eigene Sessions auflisten
GET/api/v2/usage.ledger?limit=…Gutschriftenverlauf: Verbrauch je Lauf + Kontobewegungen

Credits

Jeder Lauf wird in Credits abgerechnet — dieselbe Währung wie im Produkt, abhängig von Stufe, Werkzeugnutzung und Sandbox-Zeit (ein kurzer Fast-Lauf kostet wenige Credits). Den Verbrauch je Lauf sehen Sie im Produkt unter Einstellungen → Nutzung oder per usage.ledger. Reicht das Guthaben nicht, antwortet die API mit einem klaren Fehler statt einen Lauf anzubrechen; Credits sind jederzeit im Produkt zukaufbar.

Rate-Limits & Parallelität

PlanAnfragenGleichzeitige LäufeCredits
Fast60 / min2 parallele Läufe250 Credits / Tag
Smart120 / min3 parallele Läufe5.000 Credits / Monat
Genius240 / min5 parallele Läufe25.000 Credits / Monat
Government & Legal240 / min5 parallele Läufenach Vereinbarung

Zusätzliche Läufe über dem Parallel-Limit werden nicht abgelehnt, sondern eingereiht und starten automatisch, sobald ein Platz frei wird (Status in_queue). Beim Minuten-Limit antwortet die API so — bitte mit Backoff wiederholen:

HTTP/1.1 429 Too Many Requests
retry-after: 60

{ "ok": false, "error": { "code": "rate_limited",
  "message": "Zu viele Anfragen (60/min für diese Stufe). Bitte in 60s erneut versuchen." } }

Kontingent-Kopfzeilen: Jede Antwort trägt Ihren aktuellen Stand, damit Sie Ihre Aufrufrate steuern können, ohne sie zu erraten:

KopfzeileBedeutung
X-RateLimit-LimitAnfragen pro Minute für Ihren Plan
X-RateLimit-Remainingim laufenden Fenster noch frei
X-RateLimit-ResetSekunden bis zum Zurücksetzen
Retry-Afternur bei 429: Sekunden bis zum nächsten Versuch

Anfragegröße: Der Rumpf einer Anfrage ist auf 4 MB begrenzt (darüber 413 payload_too_large). Das reicht für sehr lange Prompts; größere Inhalte senden Sie als Datei-Anhang. Kaufpfade (Plan-Auswahl, Checkout) sind vom Minuten-Limit ausgenommen.

Für Lastspitzen, dedizierte Kapazität und höhere Kontingente (Enterprise, Load-Balancing über reservierte Sandbox-Pools) sprechen Sie uns an: info@xenori.ai.

Webhooks

Statt zu pollen lassen Sie sich benachrichtigen. Xenori schickt zwei Ereignisse an eine Adresse Ihrer Wahl: task_created, sobald eine Aufgabe angelegt wurde, und task_stopped, sobald sie fertig ist, gescheitert ist oder auf eine Eingabe wartet. Bewusst nur diese zwei — jeder Zwischenschritt gehört in den Ereignisstrom, nicht in Ihr Postfach.

curl -X POST https://xenori.ai/api/v2/webhook.create \
  -H "x-maxicore-api-key: $XENORI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://ihre-anwendung.example/xenori-hook",
    "events": ["task_created", "task_stopped"]
  }'

Ihr Endpunkt bekommt einen HTTP-POST mit dieser Nutzlast. Antworten Sie innerhalb von zehn Sekunden mit Status 200; alles andere gilt als Fehlschlag und wird wiederholt.

{
  "event_id": "task_stopped_task_abc123",
  "event_type": "task_stopped",
  "task_detail": {
    "task_id": "task_abc123",
    "task_title": "Quartalsbericht erstellen",
    "task_url": "https://xenori.ai/chat/task_abc123",
    "status": "done"
  }
}

Echtheit prüfen — Pflicht

Jede Zustellung ist mit RSA-SHA256 signiert. Prüfen Sie die Signatur, bevor Sie den Inhalt verwenden — sonst kann jeder, der Ihre Adresse kennt, Ereignisse erfinden. Sie erhalten zwei Kopfzeilen: X-Webhook-Signature (Base64) und X-Webhook-Timestamp (Unix-Sekunden). Signiert wird die Zeichenkette {timestamp}.{url}.{sha256_hex(body)} — der Zeitstempel und die Adresse gehören dazu, damit eine abgefangene Zustellung nicht andernorts wiedereingespielt werden kann. Den öffentlichen Schlüssel holen Sie einmalig von GET /api/v2/webhook.publicKey.

# Signatur pruefen (Python) — RSA-SHA256 ueber
# "{timestamp}.{url}.{sha256_hex(body)}"
import base64, hashlib, time
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

def ist_echt(kopfzeilen, url, rumpf_bytes, oeffentlicher_schluessel_pem):
    signatur = base64.b64decode(kopfzeilen["X-Webhook-Signature"])
    zeitstempel = int(kopfzeilen["X-Webhook-Timestamp"])

    # Aelter als fuenf Minuten: ablehnen (Schutz vor Wiedereinspielung)
    if abs(time.time() - zeitstempel) > 300:
        return False

    rumpf_hash = hashlib.sha256(rumpf_bytes).hexdigest()
    signiert = f"{zeitstempel}.{url}.{rumpf_hash}".encode()

    schluessel = serialization.load_pem_public_key(oeffentlicher_schluessel_pem)
    try:
        schluessel.verify(signatur, signiert, padding.PKCS1v15(), hashes.SHA256())
        return True
    except Exception:
        return False

Weisen Sie Zustellungen ab, deren Zeitstempel älter als fünf Minuten ist. Verwalten und widerrufen können Sie Ihre Webhooks im Produkt unter Einstellungen → Entwickler.

Fehlerformat

Alle Fehler kommen in einem einheitlichen Umschlag — Ihr Code braucht genau einen Fehlerpfad:

{ "ok": false, "request_id": "req_…",
  "error": { "code": "not_found | invalid_argument | rate_limited | …",
             "message": "menschenlesbare Erklärung" } }

Komplettbeispiel (Python)

import os, time, requests

BASE = "https://xenori.ai/api/v2"
H = {"x-maxicore-api-key": os.environ["XENORI_API_KEY"]}

r = requests.post(f"{BASE}/task.create", headers=H, json={
    "message": {"content": [{"type": "text",
        "text": "Fasse die wichtigsten EU-KI-Regeln in 5 Punkten zusammen."}]},
    "model": "max-smart",
})
task = r.json()["task"]

while task["status"] in ("running", "in_queue", "waiting"):
    time.sleep(4)
    task = requests.get(f"{BASE}/task.detail",
                        headers=H, params={"task_id": task["id"]}).json()["task"]

verlauf = requests.get(f"{BASE}/task.listMessages", headers=H,
                       params={"task_id": task["id"], "limit": 200}).json()
print(task["status"], "→", len(verlauf.get("messages", [])), "Nachrichten")