OpenAI Chat Completions on a SpicyAPI text model
Accepts an OpenAI Chat Completions request. messages, tools, tool_choice, parallel_tool_calls, response_format, max_tokens (or max_completion_tokens), temperature, top_p, top_k, seed and stop map onto the model's public input fields of the same name when the model declares them (each model page lists its own set); stream, stream_options, user, metadata and store are handled by this layer. Pure sampling parameters the model does not declare (temperature, top_p, top_k, min_p, top_a, frequency_penalty, presence_penalty, repetition_penalty), n: 1, an empty stop, stop on a model without stop sequences, reasoning_effort on a model without reasoning levels, and an OpenRouter-style reasoning object that cannot be translated are ignored, and the response lists them in the X-Spicy-Ignored-Params header. Values the model declares but cannot take as sent are changed to the nearest accepted value and listed as name=value in the X-Spicy-Adjusted-Params header: a sampling value outside the model's range is clamped to the bound, a stop list longer than the model allows keeps its first entries, a reasoning_effort level the model does not offer becomes the nearest level it does (the lower one on a tie), and reasoning.effort (or reasoning.enabled: false, as none) becomes reasoning_effort. Any other parameter is forwarded to the model's input schema and rejected with 400 when the model does not declare it.
stream: true returns a Server-Sent Events stream of chat.completion.chunk objects terminated by data: [DONE]. Every chunk has a non-empty choices array and each choice ends with exactly one chunk carrying finish_reason. Usage follows OpenAI: a stream carries no usage unless stream_options.include_usage is true, in which case one extra chunk with choices: [] and the final usage comes right before [DONE] and every other chunk has usage: null. stream: false returns one chat.completion object that always has usage. The same hold, settlement and refund rules as /api/v1/jobs/stream apply; the X-Spicy-Task-Id response header names the task that holds the charge.
A non-streaming call that is still running after about 30 seconds is kept open: the 200 status and the X-Spicy-Keepalive: 1 header go out first, followed by a newline every 15 seconds and then the JSON body. A failure after that point is the usual {"error": {...}} object in the body of that 200 response, so check for an error key when the header is present. The same applies to /v1/responses, /v1/messages (Anthropic error object) and :generateContent (Gemini error object, whose error.code keeps the HTTP status the error would have had).
Errors a client can act on: an unknown model returns 404 with code: model_not_found, the ID shape (publisher/model/chat) and the closest callable chat model; a model that is not a chat model returns 400 with param: model; a field or message part the model does not accept (for example an image_url part on a text-only model) returns 400 with code: unsupported_parameter and param pointing at it; a content-policy refusal returns 400 with code: content_rejected.
Request
- Base URL: https://api.spicyapi.ai
- URL: https://api.spicyapi.ai/v1/chat/completions
- Auth: HTTP bearer
Headers
Stable key for one logical task submission; retained for 24 hours per account and bound to both the submitting API key and normalized request fingerprint. A sibling key receives 409 without the original task ID.
Request body
Response
One chat.completion object, or an SSE stream when stream is true.
Changes
No recorded changes to this operation across all 1 revision of this API.