Same Path, Different Shape: How /chat/completions Differs Per Backend on One Aggregator
One aggregator exposes multiple models behind a single OpenAI-compatible /chat/completions endpoint. This article explains how request and response field shapes differ per backend (Claude, GPT, DeepSeek, Qwen, GLM, Kimi), which optional fields may be silently dropped, and how to write portable code.
The Illusion of Uniformity
An OpenAI-compatible /chat/completions endpoint gives you a single URL and a single key for many models. But behind the scenes, each backend (Claude, GPT, DeepSeek, Qwen, GLM, Kimi) has its own request and response schema. The aggregator translates as much as it can, but not every field survives the trip.
Core Fields That Always Work
model: The model identifier string. Always required.messages: An array of objects withroleandcontent. The rolessystem,user, andassistantare universally supported.stream: Boolean to enable server-sent events. Works across all backends.temperature,topp,maxtokens: Typically supported, though valid ranges and defaults may differ.
These fields form the portable subset. If you stick to them, your code will work with any model on the aggregator.
Where Backends Diverge
System Message Placement
Some backends treat the system message as a separate top-level parameter, while others expect it as the first message in the array. The aggregator normalizes this, but the effective behavior can differ: for example, some models weigh system instructions differently when they appear as a message versus a dedicated field.
Tool / Function Calling
The OpenAI-style tools and tool_choice fields are not uniformly supported. Claude and GPT backends handle them natively; others may accept the fields but ignore them or return an error. If a backend does not support tool calling, the aggregator may silently drop the tools array, leading to a plain text response instead of a tool call.
Response Format
The responseformat parameter (e.g., { "type": "jsonobject" }) is another common divergence. Some models support structured JSON output, others do not. When unsupported, the aggregator might drop the field and return free-form text. Always validate that the response is valid JSON if you rely on this.
Multimodal Input
Fields like image_url inside message content are only supported by certain models. If you send an image to a text-only backend, the aggregator may strip the image part or reject the request. Check model capabilities before sending multimodal content.
Logprobs and Top-Logprobs
These are rarely supported outside of OpenAI models. The aggregator may ignore them entirely, so do not depend on log probabilities unless you have verified support.
Response Shape Variations
The top-level response structure is standardized: id, object, created, model, choices, and usage. However:
usagemay be absent or have missing fields for some backends. Token counts might be estimated or omitted.choices[].finishreasoncan vary:stop,length,toolcalls, orcontent_filterare common, but some backends returnnullor custom strings.- The
modelfield in the response may reflect the actual backend model name, which could differ from the one you requested if the aggregator routes to a versioned variant.
Which Optional Fields Get Silently Dropped
Based on common aggregator behavior, these fields are often dropped without warning when unsupported by the backend:
logprobs,top_logprobstools,tool_choice(if backend lacks function calling)response_format(if backend lacks structured output)seed(for deterministic sampling)presencepenalty,frequencypenalty(some backends ignore them)stopsequences (may be ignored or limited in count)useridentifier (often stripped for privacy)
Always test your specific use case with the target model to confirm which fields are honored.
Writing Portable Code
- Stick to the core fields when possible:
model,messages,stream,temperature,max_tokens. - Feature-detect by checking model documentation or making a test call before relying on advanced fields.
- Handle missing fields gracefully in responses: do not assume
usageorfinish_reasonwill always be present. - Validate structured output if you requested JSON, as the backend might not enforce it.
- Use a fallback strategy for tool calling: if the response lacks tool calls, parse the text output.
Why This Matters for Cost and Access
On this aggregator, you pay the official price multiplied by 1.3 for any model, and you can top up with USDC on Base without KYC. If you contribute a key to the pool, you earn credits at official price × 1.1 (or × 1.2 for premium models) in USDC. Understanding these per-backend differences helps you avoid wasted calls and ensures your application behaves consistently across models.