Core Models (LLM API)
apodex-1.1 and apodex-1.1-mini — direct, OpenAI-compatible access to the underlying language models, with no agent loop in between.
/v1/chat/completionshttps://api.apodex.aiOverview
Core models are the Apodex language models themselves, exposed over the standard OpenAI wire format — no planning loop, no web search, no tools running on our side. Point the official openai SDK at the base URL below and your existing code works unchanged. They share the /v1/chat/completions path with the deep research models but deliberately behave differently — read the comparison table before you switch.
The same models are also reachable over the Anthropic protocol at POST /v1/messages, at identical prices — see Anthropic Messages API if your client already speaks that dialect (Anthropic SDKs, Claude Code).
Models
Two text-only models, both with a 262,144-token context window. Same API, same parameters — pick by capability and cost.
| Models | Best for | Parameters | Context window | List price |
|---|---|---|---|---|
Apodex 1.1 apodex-1.1 | Hard reasoning, long context, quality-critical work | 397B | 262,144 | in $0.30 · cached $0.030 · out $3.00 |
Apodex 1.1 Mini apodex-1.1-mini | High-throughput, latency- or cost-sensitive work | 35B | 262,144 | in $0.10 · cached $0.010 · out $1.00 |
/ 1M tokens
Both ids are also returned by GET /v1/models, together with their context_length and max_completion_tokens.
Quickstart
The endpoint is OpenAI-compatible: set base_url and your API key, and the official SDKs work as-is. Note that stream defaults to false here.
Headers
| Header | Value | Description |
|---|---|---|
AuthorizationRequired | Bearer YOUR_API_KEY | Your Apodex API key, sent as a bearer token. |
Content-TypeRequired | application/json | Always application/json. |
X-Session-IdOptional | <your-stable-conversation-key> | Optional. A stable key for one logical conversation — sending the same value across turns significantly improves prefix cache hit rate (lower latency, lower cost). Omit it and the server derives a key from the request content. |
Request
curl -X POST https://api.apodex.ai/v1/chat/completions \
-H "Authorization: Bearer $APODEX_API_KEY" \
-H "Content-Type: application/json" \
-H "X-Session-Id: my-conversation-42" \
-d '{
"model": "apodex-1.1",
"messages": [
{"role": "user", "content": "Explain prefix caching in one paragraph."}
],
"max_tokens": 512,
"temperature": 0.7
}'Response
{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1712345678,
"model": "apodex-1.1",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"reasoning_content": "The user wants a one-paragraph explanation...",
"content": "Prefix caching reuses..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 42,
"completion_tokens": 187,
"total_tokens": 229,
"prompt_tokens_details": { "cached_tokens": 32 }
}
}Supported parameters
Sampling parameters are passed through to the model natively — no rewriting, no silent clamping.
| Parameter | Support |
|---|---|
model | Required. apodex-1.1 or apodex-1.1-mini. |
messages | Required. Standard OpenAI chat messages. Text content only. |
stream | Optional, defaults to false. Set true for SSE streaming — required for generations longer than 32768 tokens. |
stream_options | Optional, streaming only. Set include_usage: true to receive a final chunk carrying the usage object — same behaviour as OpenAI. Without it, streamed responses omit usage; billing is unaffected either way. |
max_tokens | Optional. Passed through natively. Capped at 32768 when stream is false; uncapped (up to the context window) when streaming. Reasoning tokens count toward this budget — see Limits. |
temperature | Optional. Passed through natively. |
top_p | Optional. Passed through natively. |
stop | Optional. Passed through natively. |
seed | Optional. Passed through natively; best-effort determinism only. |
n | Only n = 1 is supported. |
Core models vs. deep research models
Both model families answer on POST /v1/chat/completions, and the semantics are deliberately different. The behaviour is selected by the model id in the request body, so switching model ids also switches the contract.
| Aspect | Core models (apodex-1.1, apodex-1.1-mini) | Deep research models (Deep Research / Solve / Discover tiers) |
|---|---|---|
| Default for stream | false — a plain JSON response unless you opt in | true — SSE unless you explicitly opt out |
| Failure mode | Real HTTP status codes: 400 / 401 / 402 / 429 | HTTP 200 even on failure; the error is carried inside the stream or body |
| Sampling parameters | max_tokens, temperature and top_p are passed through natively | Ignored — the agent controls its own generation budget |
| Tools | None. Nothing runs server-side; you get the model output only | Built-in web search, URL fetch, code sandbox, MCP servers |
| Latency profile | Single forward pass — first token in the usual LLM range | Minutes: the agent plans, searches and iterates before answering |
| Billing unit | Real tokens: input / cached input / output | Tokens plus per-use tool calls |
The deep research contract is documented separately in Chat Completions.
Limits and restrictions
| Limit | Description |
|---|---|
| Non-streaming max_tokens is capped at 32768 | With JSON |
| A non-streaming request is capped at about 600s of wall clock | Independently of This can bite you well inside the 32768 cap. Under high concurrency with cold prefix caches, decoding slows down, so a request that normally completes in about 190s can approach the wall. Our advice: stream anything long, and if you must stay non-streaming, set your client timeout to 600s or more — several SDKs default to exactly 600s, which lands right on the boundary. |
| Reasoning is on by default and counts toward max_tokens | Both models think before answering. The reasoning text is returned in the If |
| The Responses API subset is stateless | Core models support a stateless subset of POST /v1/responses: store is forced to false. Sending store: true, previous_response_id or background: true returns HTTP 400 — carry the conversation in your own request instead. |
| Text only | Multimodal input is not supported. Image, audio and file content parts are rejected — send text. |
| Account-level rate limits | Concurrency and tokens-per-minute are enforced per account and surface as HTTP 429. See Rate limits for the full contract. |
Responses API subset
POST /v1/responses is supported as a stateless subset: single-shot request in, response out. Anything that would require us to persist state on your behalf is rejected with HTTP 400 rather than silently ignored.
| Parameter | Support |
|---|---|
store | Forced to false. Sending store: true returns 400. |
previous_response_id | Not supported — returns 400. There is no server-side conversation to resume. |
background | Not supported — returns 400. Requests are always executed inline. |
max_output_tokens | Supported. Maps to max_tokens, including the 32768 non-streaming cap. |
curl -X POST https://api.apodex.ai/v1/responses \
-H "Authorization: Bearer $APODEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "apodex-1.1",
"input": "Explain prefix caching in one paragraph.",
"max_output_tokens": 512
}'Session caching with X-Session-Id
Sending the optional X-Session-Id header with a stable value for one logical conversation lets us route the turns of that conversation consistently, which significantly improves prefix cache hit rate — lower time-to-first-token and a cheaper cached-input rate on the shared prefix. If you omit the header, the server derives a key from the request content automatically.
- Use one stable, unique value per conversation — a UUID per chat thread is ideal.
- Reuse the same value for every turn of that conversation, including retries of the same turn.
- Do not reuse one value across unrelated conversations, and do not put user identifiers or other sensitive data in it.
X-Session-Id: <your-stable-conversation-key>Billing
Core models are billed on real token counts reported by the model, in three tiers:
- Input — prompt tokens that were not served from cache.
- Cached input — prompt tokens served from the prefix cache, billed at a lower rate than fresh input.
- Output — tokens the model generates, including any streamed partial output.
Requests with more than 200K input tokens are billed at 2× the listed rates for the entire request — the multiplier applies to input, cached input and output alike.
If the client disconnects mid-generation, the tokens already generated are still billed. Cancelling a request stops further generation but does not refund what has been produced.
Streamed responses carry the usage object only when the request sets include_usage: true in stream_options — the final chunk then reports it, exactly like OpenAI. Omitting it does not change billing: usage is metered server-side either way.
Current list prices are on the Pricing page.
Error responses
Unlike the deep research models, core models return real HTTP status codes. Errors are never wrapped in a 200 response.
| Status | Code | Description |
|---|---|---|
400 | invalid_request | Invalid parameters — malformed body, unsupported field, multimodal content, or max_tokens above 32768 on a non-streaming request. |
400 | model_not_found | Unknown model id, or a model your account is not entitled to. Returned as HTTP 400, not 404. |
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Insufficient balance. Top up in the console and retry. |
429 | rate_limited | Rate limited — account concurrency or TPM exceeded. Honour Retry-After and back off. |
HTTP/1.1 400 Bad Request
{
"error": {
"message": "model not found: gpt-4o",
"type": "invalid_request_error",
"code": "model_not_found"
}
}