Von OpenAI oder OpenRouter migrieren
OpenAI-Bibliotheken mit SpicyAPI verbinden: Basis-URL, Key und Modell-ID ändern, Feldunterschiede beachten und OpenRouter-Zusätze entfernen.
Ruft Ihr Code bereits ein Chatmodell über offizielle OpenAI-Bibliotheken oder ein Werkzeug mit „OpenAI-kompatibel“-Einstellung auf, ändern Sie für SpicyAPI drei Dinge: Basis-URL, API-Key und Modell-ID. Diese Seite nennt die Änderungen und abweichendes Verhalten, damit die Migration nicht mit unerwartetem 400 endet. Vollständige Programme finden Sie unter Chatbeispiele.
Die drei Änderungen
| Einstellung | Wert bei SpicyAPI |
|---|---|
| Basis-URL | https://api.spicyapi.ai/v1 |
| API-Key | SpicyAPI-Key mit sk-spicy-, als Authorization: Bearer gesendet |
| Modell | Exakte Textmodell-ID aus Livekatalog, etwa in SPICY_MODEL, siehe Modell-IDs |
import os
from openai import OpenAI
# Before: client = OpenAI() (reads OPENAI_API_KEY, calls api.openai.com)
client = OpenAI(api_key=os.environ["SPICY_API_KEY"], base_url="https://api.spicyapi.ai/v1")
reply = client.chat.completions.create(
model=os.environ["SPICY_MODEL"],
messages=[{"role": "user", "content": "Say hello in one sentence."}],
)
print(reply.choices[0].message.content)OpenAI-Bibliotheken lesen auch OPENAI_BASE_URL und OPENAI_API_KEY aus der Umgebung. Damit kann bestehender Code unverändert laufen; allerdings werden alle übrigen OpenAI-Aufrufe desselben Prozesses ebenfalls umgeleitet. Bevorzugen Sie deshalb ausdrückliche Übergabe wie oben.
Modell-IDs
Textmodell-IDs haben das Format publisher/model/chat. Kopieren Sie sie aus dem Livekatalog, statt bekannte Namen anderer Dienste zu übertragen:
GET /api/v1/models?modality=textlistet nur Textmodelle mit Preisen und ergänzt mitincludeSchema=1dereninputSchema. Siehe Modellkatalog und Schemas.GET /v1/modelsist die von Werkzeugen gelesene OpenAI-Liste. Ohne Filter enthält sie Bild-, Video- und Audiomodelle, die unter/v1/chat/completionsnicht aufrufbar sind. Ergänzen Sie?modality=textfür ausschließlich Text. Neben vier OpenAI-Feldern enthält jeder Eintragmodalityundtask; Chatmodelle zusätzlichcontext_length,max_output_tokensundsupported_parameters, die akzeptierten Anfragefelder. OpenAI-Bibliotheken ignorieren Zusatzfelder.
Nicht existierende IDs liefern 404 mit code: "model_not_found" und param: "model". Die Meldung nennt das ID-Format und, sofern vorhanden, das nächstähnliche aufrufbare Chatmodell. Bild- oder Videomodell an Chatendpunkt liefert 400 mit Hinweis, dass es kein Chatmodell ist. IDs anderer Dienste können ähnlich aussehen, sind aber nicht austauschbar: Herstellernamen unterscheiden sich, Suffixe wie :free existieren hier nicht und Textmodelle enden mit /chat.
Anfragefelder
Jedes Modell veröffentlicht akzeptierte Felder in inputSchema und als Namen in supported_parameters unter /v1/models.
- Nicht gelistete Sampling-Felder werden ignoriert.
temperature,top_p,top_k,min_p,top_a,frequency_penalty,presence_penaltyundrepetition_penaltybeeinflussen nur Zufälligkeit oder Wiederholung. Viele Clients senden sie standardmäßig; Modelle ohne Unterstützung generieren einfach ohne sie. Dasselbe gilt fürn: 1, leeresstop,stopohne modellseitige Stopsequenzen undreasoning_effortohne Denkstufen. Ignorierte Felder nennt der AntwortheaderX-Spicy-Ignored-Params, etwafrequency_penalty, presence_penalty. - Nicht akzeptierte Werte werden zum nächsten erlaubten Wert geändert. Sampling außerhalb des Modellbereichs wird auf die Grenze begrenzt, eine zu lange
stop-Liste auf die ersten erlaubten Einträge gekürzt, und nicht angebotenereasoning_effort-Stufen werden zur nächstliegenden verfügbaren Stufe, bei Gleichstand zur niedrigeren. Änderungen stehen alsname=valueinX-Spicy-Adjusted-Params, etwareasoning_effort=low, temperature=1. - Alle anderen nicht gelisteten Felder werden abgelehnt, mit
400,code: "unsupported_parameter", dem Feld unterparamund konkreter Meldung, etwalogprobs: is not a supported field. Diese Felder verändern das Ergebnis; Sie bezahlen daher nicht für eine Antwort, die Ihre vermeintlich aktive Option nicht verwendete.
| Feld | Bei SpicyAPI |
|---|---|
messages | Gleiche Struktur; Rollen system, developer, user, assistant, tool. Text überall; image_url-Teile nur bei Modellen, deren Schema sie aufführt |
max_tokens, max_completion_tokens | Beide mit gleicher Bedeutung akzeptiert. Denktokens zählen mit; Standard und Maximum je Modell |
stream, stream_options | Unterstützt mit OpenAI-Verbrauchsregeln: Stream enthält Verbrauch nur bei include_usage gleich true, siehe Antworten und Streams |
tools, tool_choice | Bei jedem Textmodell unterstützt. Manche erlauben nur auto und none für tool_choice; erzwungenes benanntes Werkzeug ergibt dort 400 |
parallel_tool_calls | Nur bei explizit gelisteten Modellen |
reasoning_effort | Bei meisten Modellen, aber Werte unterscheiden sich: Manche bieten none, minimal, xhigh, max, manche kein medium. Nicht angebotene Stufe wird zur nächstliegenden geändert; lesen Sie für exakte Stufe enum |
temperature, top_p, top_k, frequency_penalty, presence_penalty | Bei gelisteten Modellen genutzt und auf Bereich begrenzt; sonst ignoriert und in X-Spicy-Ignored-Params genannt. Mehrere Modelle unterstützen keine Sampling-Felder |
seed | Nur bei gelisteten Modellen |
stop | Bei gelisteten Modellen genutzt und auf maximale Anzahl gekürzt; bei fehlender Stopsequenz-Unterstützung oder leerer Liste ignoriert |
response_format | json_object bei Modellen mit diesem Feld; sonst nicht verfügbar |
user, metadata, store | Akzeptiert und ignoriert |
n | 1 ignoriert; andere Werte bei Modellen ohne dieses Feld mit 400 abgelehnt |
logprobs, top_logprobs, logit_bias und andere nicht gelistete Felder | Mit 400 abgelehnt |
Prüfen Sie vor dem Senden Felder und Werte mit dem Befehl unter Chatbeispiele: Vor dem Start.
Antworten und Streams
Eine nicht gestreamte Antwort ist ein normales chat.completion-Objekt; reply.choices[0].message.content und reply.usage funktionieren wie bisher. Unterschiede sind gering:
reasoning_content. Denkende Modelle liefern Denktext inmessage.reasoning_content, beim Streaming indelta.reasoning_content, nebencontent. Er zählt bereits zuusage.completion_tokens.- ID entspricht Anfrage-ID.
idhat das Formatchatcmpl-req_...; Antwortheaderx-request-identhält denselbenreq_...-Wert. Nennen Sie ihn beim Support. Ein zweiter HeaderX-Spicy-Task-Idbezeichnet den Task mit der Belastung, siehe Kosten und Verbrauch. - Kein
system_fingerprintund keinelogprobs.
Streams verwenden dieselben chat.completion.chunk-Ereignisse, enden mit data: [DONE] und folgen OpenAI-Verbrauchsregeln:
- Verbrauch nur auf Anforderung. Ohne
stream_options.include_usageenthält kein Chunkusage; alle haben nicht leerechoices. Mit"include_usage": trueerscheint direkt vor[DONE]ein zusätzlicher Chunk mit leeremchoicesund endgültigemusage; alle anderen enthaltenusage: null. Code aus OpenAI-Streamingbeispielen funktioniert unverändert. Prüfen Siechoicesvor Zugriff aufchoices[0], um den letzten Chunk sicher zu behandeln. - Ein
finish_reasonje Auswahl. Jede Auswahl endet unabhängig vom Modell mit genau einem Chunk mitfinish_reason. - Keep-alive-Zeilen. Während Modellnachdenken hält
: keep-aliveals Kommentar die Verbindung offen. OpenAI-Bibliotheken überspringen diese; eigene Parser müssen das ebenfalls.
Streamen Sie lange Antworten oder hohen reasoning_effort. Nicht gestreamte Anfragen über etwa 30 Sekunden bleiben durch Leerraum vor JSON und X-Spicy-Keepalive: 1 offen, sodass OpenAI-Bibliotheken sie weiter parsen. Scheitern sie danach, kommt das Fehlerobjekt jedoch im Inhalt einer 200-Antwort, die Bibliotheken nicht als Fehler auslösen. Siehe Timeouts und Streaming.
Fehler
Fehler verwenden die OpenAI-Struktur {"error": {"message", "type", "param", "code"}} mit üblichen HTTP-Statuscodes. Die Bibliotheken lösen ihre gewohnten Exceptions aus. param benennt das Feld als Punktpfad wie temperature oder messages.1.content.0. code unterscheidet gleiche Status: unsupported_parameter für nicht akzeptiertes Feld oder Nachrichtenteil, invalid_request für fehlendes Feld oder nicht akzeptierten Wert, content_rejected für Inhaltsablehnung ebenfalls mit 400 und model_not_found mit 404. Anders als OpenAI verwendet SpicyAPI 402, wenn Guthaben oder Ausgabenlimit die Anfrage nicht deckt. Vollständige Tabelle mit Maßnahmen unter Chatbeispiele: Fehlerbehebung.
OpenAI-Bibliotheken wiederholen 429 und 5xx selbst. Das ist hier sicher: Fehlgeschlagene Anfragen werden nicht berechnet. Senden Sie Idempotency-Key je Aufruf und lesen vorher Idempotenzschlüssel für Textendpunkte.
Kosten und Verbrauch
Antworten nennen Tokenzahlen in usage, keinen Preis. Eingabe, Cacheeingabe und Ausgabe werden je Million Tokens bepreist; Preise stehen auf Modellseite und im Katalog. Für tatsächliche Kosten lesen Sie den bei jeder angenommenen Anfrage mit oder ohne Stream vorhandenen Antwortheader X-Spicy-Task-Id (job_…) und fragen GET /api/v1/jobs/recordInfo?taskId=<job_…> ab: cost ist endgültig bei settled gleich true. Einträge in GET /api/v1/jobs enthalten auch die requestId des erstellenden Aufrufs aus X-Request-Id; Konsole → Logs zeigt dieselben Tasks. Headerlesen mit OpenAI-Bibliotheken unter Chatbeispiele: Aufrufkosten ermitteln; außerdem Preisabfragen und Abrechnung.
Vor Ausführung wird ein Betrag für Nachrichten plus vollständige Ausgabe-max_tokens, bei Weglassen Modellstandard, reserviert. Berechnet wird nur Nutzung, aber die Reservierung muss zunächst gedeckt sein. Kleines Guthaben mit großem max_tokens liefert daher 402. Setzen Sie realistische max_tokens oder Key-Ausgabenlimits; siehe Abrechnung.
Hier nicht verfügbare Endpunkte
Textgenerierung bietet OpenAI Chat Completions, OpenAI Responses, Anthropic Messages und Google Gemini. Details unter Text und Streaming. Diese OpenAI-Endpunkte existieren nicht und liefern 404: /v1/embeddings, veraltetes /v1/completions, /v1/images/*, /v1/audio/*, /v1/moderations, /v1/files, /v1/batches, /v1/assistants und Fine-Tuning. Bild-, Video- und Audiomodelle verwenden stattdessen die Task-API, Videos zusätzlich /v1/videos.
Von OpenRouter wechseln
Auch OpenRouter nutzt OpenAI-Format. Die drei Änderungen gelten daher ebenfalls: Basis-URL https://openrouter.ai/api/v1 durch https://api.spicyapi.ai/v1 ersetzen, Key und Modell-IDs austauschen. Entfernen Sie dann OpenRouter-spezifische Felder, die hier 400 liefern:
| OpenRouter-Feld | Maßnahme |
|---|---|
models als Ausweichliste und route | Entfernen. Eine Modell-ID senden; SpicyAPI bestimmt die Ausführung |
provider | Entfernen. Keine Auswahl des ausführenden Dienstes je Anfrage |
reasoning, etwa {"effort": "high"} | Wird zu oberstem reasoning_effort; enabled: false wird zu none, sofern modellseitig verfügbar. Andere Objektschlüssel werden ignoriert. Direktes reasoning_effort ist klarer |
usage mit {"include": true} | Entfernen. Nicht gestreamte Antworten enthalten immer usage; bei Stream stream_options: {"include_usage": true} senden |
transforms, plugins | Entfernen |
Header HTTP-Referer und X-Title sind unschädlich und werden ignoriert.
Checkliste
- Basis-URL
https://api.spicyapi.ai/v1und SpicyAPI-Key. - Modell-ID aus Livekatalog mit
/chatam Ende. - Anfragefelder gegen Modell-
inputSchemageprüft; nicht unterstützte Nicht-Sampling-Felder entfernt, AntwortheaderX-Spicy-Ignored-ParamsundX-Spicy-Adjusted-Paramseinmal auf Änderungen geprüft. - Bei
stream_options.include_usageüberspringt die Schleife den letzten Chunk mit leeremchoices. - Realistisches
max_tokensoder Modellstandard, ergänzt um Key-Ausgabenlimits. - Lange oder aufwendige Denkanfragen verwenden
stream: true.
Weiterlesen
Chatbeispiele · Text und Streaming · Modellkatalog und Schemas · Authentifizierung · Abrechnung
Chatbeispiele
Vollständige ausführbare Programme für mehrteilige Gespräche, Figurenrollenspiel, Streaming in eigene Oberflächen und Werkzeugaufrufe mit Python, Node.js und curl.
Tutorial: Ein Bild in ein Video verwandeln
Sie beginnen mit einem Bild auf Ihrem Computer und halten am Ende eine heruntergeladene Videodatei in der Hand. Jeder Schritt zeigt die CLI, das TypeScript-SDK und reines HTTP.

