For models that support it, the OpenRouter API can return Reasoning Tokens, also known as thinking tokens. OpenRouter normalizes the different ways of customizing the amount of reasoning tokens that the model will use, providing a unified interface across different providers.
Reasoning tokens provide a transparent look into the reasoning steps taken by a model. Reasoning tokens are considered output tokens and charged accordingly.
Reasoning tokens are included in the response by default if the model decides to output them. Reasoning tokens will appear in the reasoning field of each message, unless you decide to exclude them.
While most models and providers make reasoning tokens available in the response, some (like the OpenAI o-series) do not.
You can control reasoning tokens in your requests using the reasoning parameter:
The reasoning config object consolidates settings for controlling reasoning strength across different models. See the Note for each option below to see which models are supported and how other models will behave.
Currently supported by:
Anthropic reasoning models (by using the reasoning.max_tokens
parameter)
thinking_budget)For Alibaba, support varies by model — please check the individual model descriptions to confirm
whether reasoning.max_tokens (via thinking_budget) is available.
For models that support reasoning token allocation, you can control it like this:
"max_tokens": 2000 - Directly specifies the maximum number of tokens to use for reasoningFor models that only support reasoning.effort (see below), the max_tokens value will be used to determine the effort level.
Currently supported by OpenAI reasoning models (o1 series, o3 series, GPT-5 series) and Grok models
"effort": "xhigh" - Allocates the largest portion of tokens for reasoning (approximately 95% of max_tokens)"effort": "high" - Allocates a large portion of tokens for reasoning (approximately 80% of max_tokens)"effort": "medium" - Allocates a moderate portion of tokens (approximately 50% of max_tokens)"effort": "low" - Allocates a smaller portion of tokens (approximately 20% of max_tokens)"effort": "minimal" - Allocates an even smaller portion of tokens (approximately 10% of max_tokens)"effort": "none" - Disables reasoning entirelyFor models that only support reasoning.max_tokens, the effort level will be set based on the percentages above.
If you want the model to use reasoning internally but not include it in the response:
"exclude": true - The model will still use reasoning, but it won’t be returned in the responseReasoning tokens will appear in the reasoning field of each message.
To enable reasoning with the default parameters:
"enabled": true - Enables reasoning at the “medium” effort level with no exclusions.For models that support direct token allocation (like Anthropic models), you can specify the exact number of tokens to use for reasoning:
If you want the model to use reasoning internally but not include it in the response:
This example shows how to use reasoning tokens in a more complex workflow. It injects one model’s reasoning into another model to improve its response quality:
To preserve reasoning context across multiple turns, you can pass it back to the API in one of two ways:
message.reasoning (string): Pass the plaintext reasoning as a string field on the assistant messagemessage.reasoning_details (array): Pass the full reasoning_details blockUse reasoning_details when working with models that return special reasoning types (such as encrypted or summarized) - this preserves the full structure needed for those models.
For models that only return raw reasoning strings, you can use the simpler reasoning field. You can also use reasoning_content as an alias - it functions identically to reasoning.
Preserving reasoning is currently supported by these proprietary models:
And these open source models:
Note: standard interleaved thinking only. The preserved thinking feature for Z.ai models is currently not supported.
The reasoning_details functionality works identically across all supported reasoning models. You can easily switch between OpenAI reasoning models (like ~openai/gpt-latest) and Anthropic reasoning models (like ~anthropic/claude-sonnet-latest) without changing your code structure.
Preserving reasoning blocks is useful specifically for tool calling. When models like Claude invoke tools, it is pausing its construction of a response to await external information. When tool results are returned, the model will continue building that existing response. This necessitates preserving reasoning blocks during tool use, for a couple of reasons:
Reasoning continuity: The reasoning blocks capture the model’s step-by-step reasoning that led to tool requests. When you post tool results, including the original reasoning ensures the model can continue its reasoning from where it left off.
Context maintenance: While tool results appear as user messages in the API structure, they’re part of a continuous reasoning flow. Preserving reasoning blocks maintains this conceptual flow across multiple API calls.
When providing reasoning_details blocks, the entire sequence of consecutive reasoning blocks must match the outputs generated by the model during the original request; you cannot rearrange or modify the sequence of these blocks.
For more detailed information about thinking encryption, redacted blocks, and advanced use cases, see Anthropic’s documentation on extended thinking.
For more information about OpenAI reasoning models, see OpenAI’s reasoning documentation.
When reasoning models generate responses, the reasoning information is structured in a standardized format through the reasoning_details array. This section documents the API response structure for reasoning details in both streaming and non-streaming responses.
The reasoning_details field contains an array of reasoning detail objects. Each object in the array represents a specific piece of reasoning information and follows one of three possible types. The location of this array differs between streaming and non-streaming responses.
reasoning_details appears in choices[].message.reasoning_detailsreasoning_details appears in choices[].delta.reasoning_details for each chunkAll reasoning detail objects share these common fields:
id (string | null): Unique identifier for the reasoning detailformat (string): The format of the reasoning detail, with possible values:
"unknown" - Format is not specified"openai-responses-v1" - OpenAI responses format version 1"azure-openai-responses-v1" - Azure OpenAI responses format version 1"xai-responses-v1" - xAI responses format version 1"anthropic-claude-v1" - Anthropic Claude format version 1 (default)"google-gemini-v1" - Google Gemini format version 1index (number, optional): Sequential index of the reasoning detail1. Summary Type (reasoning.summary)
Contains a high-level summary of the reasoning process:
2. Encrypted Type (reasoning.encrypted)
Contains encrypted reasoning data that may be redacted or protected:
3. Text Type (reasoning.text)
Contains raw text reasoning with optional signature verification:
In non-streaming responses, reasoning_details appears in the message:
In streaming responses, reasoning_details appears in delta chunks as the reasoning is generated:
Streaming Behavior Notes:
reasoning_details array in each chunk may contain one or more reasoning objects[REDACTED] in streaming responsesFor backward compatibility, OpenRouter still supports the following legacy parameters:
include_reasoning: true - Equivalent to reasoning: {}include_reasoning: false - Equivalent to reasoning: { exclude: true }However, we recommend using the new unified reasoning parameter for better control and future compatibility.
The latest Claude models, such as ~anthropic/claude-sonnet-latest, support working with and returning reasoning tokens.
You can enable reasoning on Anthropic models only using the unified reasoning parameter with either effort or max_tokens.
Note: The :thinking variant is no longer supported for Anthropic models. Use the reasoning parameter instead.
When using Anthropic models with reasoning:
reasoning.max_tokens parameter, that value is used directly with a minimum of 1024 tokens.reasoning.effort parameter, the budget_tokens are calculated based on the max_tokens value.The reasoning token allocation is capped at 128,000 tokens maximum and 1024 tokens minimum. The formula for calculating the budget_tokens is: budget_tokens = max(min(max_tokens * {effort_ratio}, 128000), 1024)
effort_ratio is 0.95 for xhigh effort, 0.8 for high effort, 0.5 for medium effort, 0.2 for low effort, and 0.1 for minimal effort.
Important: max_tokens must be strictly higher than the reasoning budget to ensure there are tokens available for the final response after thinking.
Please note that reasoning tokens are counted as output tokens for billing purposes. Using reasoning tokens will increase your token usage but can significantly improve the quality of model responses.
Gemini 3 models (such as google/gemini-3.1-pro-preview and google/gemini-3-flash-preview) use Google’s thinkingLevel API instead of the older thinkingBudget API used by Gemini 2.5 models.
OpenRouter maps the reasoning.effort parameter directly to Google’s thinkingLevel values:
When using thinkingLevel, the actual number of reasoning tokens consumed is determined internally by Google. There are no publicly documented token limit breakpoints for each level. For example, setting effort: "low" might result in several hundred reasoning tokens depending on the complexity of the task. This is expected behavior and reflects how Google implements thinking levels internally.
If a model doesn’t support a specific effort level (for example, if a model only supports low and high), OpenRouter will map your requested effort to the nearest supported level.
If you specify reasoning.max_tokens explicitly, OpenRouter will pass it through as thinkingBudget to Google’s API. However, for Gemini 3 models, Google internally maps this budget value to a thinkingLevel, so you will not get precise token control. The actual token consumption is still determined by Google’s thinkingLevel implementation, not by the specific budget value you provide.