1. Core Concepts
  2. Thinking (Reasoning)

Pass a thinking object on your message to let the model reason before responding. Omit it or set null to disable. Pass {} for provider defaults.

thinking is a per-turn parameter — pass it on every call where you want reasoning enabled.

import requests

headers = {"X-API-Key": "YOUR_API_KEY"}
thread_id = "your-thread-id"

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "openai",
        "model_name": "o3",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
Fields

FieldTypeDescription
effortstringReasoning depth: low, medium, high, or max
budget_tokensintegerMax tokens for internal reasoning
max_tokensintegerMax tokens for reasoning output
exclude_reasoningbooleanOmit reasoning traces from response

​
Provider Support

ProviderSupported FieldsExample
OpenAIeffort{"effort": "high"}
Anthropiceffort, budget_tokens{"effort": "high"}
AWS Bedrockeffort, budget_tokens{"effort": "high"}
Google (Gemini 2.5)budget_tokens{"budget_tokens": 8192}
Google (Gemini 3)effort{"effort": "high"}
xAIeffort{"effort": "high"}
OpenRoutermax_tokens, exclude_reasoning{"max_tokens": 4096}
Cerebrasmax_tokens, exclude_reasoning{"max_tokens": 4096}

​
Provider Details

OpenAI: Models: o1, o3, o4, gpt-5 series. Default effort: medium.

Anthropic: Claude Opus 4.7 and newer (including Opus 5 and Fable 5) use adaptive thinking — pass effort (low, medium, high, max); budget_tokens is not accepted for these models. Older models (Claude 3.7 Sonnet, Sonnet 4, Opus 4–4.6) use budget_tokens (min 1,024). Backboard routes to the correct mode automatically.

AWS Bedrock: Bedrock-hosted Anthropic Claude models. Claude Opus 4.7 and newer (including Opus 5 and Fable 5) use adaptive thinking — pass effort; budget_tokens is rejected for these models. Older Bedrock Claude models accept budget_tokens (min 1,024) or effort. Backboard routes to the correct mode automatically.

Google (Gemini 2.5): Max budget: 32,768 (Pro) / 24,576 (others).

Google (Gemini 3): Uses effort (low through max). Thinking is on by default.

xAI: Reasoning models — grok-4.3 and its aliases grok-latest, grok-3*, grok-4*, grok-4-fast-reasoning, grok-4-1-fast-reasoning, grok-3-mini* — accept effort (low, medium, high, max); max maps to xAI’s highest level. Omit thinking to avoid setting a Backboard control (xAI’s own default is low); pass {} for Backboard’s default medium. The *-non-reasoning variants do not support effort.

OpenRouter / Cerebras: Use max_tokens (int > 0) and exclude_reasoning (bool).

Best for complex tasks: math, code generation, multi-step reasoning, analysis.

Thinking uses extra tokens and adds latency. Skip it for simple questions.

​
Non-Streaming Examples

Replace YOUR_API_KEY and thread_id with your values.

​
OpenAI

import requests

headers = {"X-API-Key": "YOUR_API_KEY"}
thread_id = "your-thread-id"

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "openai",
        "model_name": "o3",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
Anthropic

Use effort for Claude Opus 4.7+ (adaptive thinking). Use budget_tokens for older models.

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "anthropic",
        "model_name": "claude-opus-4-7-20250501",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
AWS Bedrock

Use effort for Claude Opus 4.7+ on Bedrock. Use budget_tokens for older Bedrock Claude models.

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "aws-bedrock",
        "model_name": "anthropic.claude-opus-4-7",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
Google (Gemini 2.5)

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"budget_tokens": 8192},
        "llm_provider": "google",
        "model_name": "gemini-2.5-pro",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
Google (Gemini 3)

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "google",
        "model_name": "gemini-3.1-pro-preview",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
xAI

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "xai",
        "model_name": "grok-4.3",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
OpenRouter

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"max_tokens": 4096},
        "llm_provider": "openrouter",
        "model_name": "minimax/minimax-m1",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
Cerebras

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {},
        "llm_provider": "cerebras",
        "model_name": "z-ai/glm-4.7",
        "stream": False
    }
)
result = response.json()
print(result["reasoning"])
print(result["content"])

​
Streaming Examples

Same as above but with "stream": True. The model thinks first, then streams the response. All Python examples below assume import json, requests and headers/thread_id are already set (see the non-streaming section above).

​
OpenAI

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "openai",
        "model_name": "o3",
        "stream": True
    },
    stream=True
)
for line in response.iter_lines():
    if line:
        decoded = line.decode()
        if decoded.startswith("data: "):
            event = json.loads(decoded[6:])
            t = event.get("type")
            if t == "reasoning_streaming":
                print(event.get("content", ""), end="", flush=True)
            elif t == "reasoning_ended":
                print("\n---------Reasoning Ended, Response Started---------")
            elif t == "content_streaming":
                print(event.get("content", ""), end="", flush=True)

​
Anthropic

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "anthropic",
        "model_name": "claude-opus-4-7-20250501",
        "stream": True
    },
    stream=True
)
for line in response.iter_lines():
    if line:
        decoded = line.decode()
        if decoded.startswith("data: "):
            event = json.loads(decoded[6:])
            t = event.get("type")
            if t == "reasoning_streaming":
                print(event.get("content", ""), end="", flush=True)
            elif t == "reasoning_ended":
                print("\n---------Reasoning Ended, Response Started---------")
            elif t == "content_streaming":
                print(event.get("content", ""), end="", flush=True)

​
AWS Bedrock

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "aws-bedrock",
        "model_name": "anthropic.claude-opus-4-7",
        "stream": True
    },
    stream=True
)
for line in response.iter_lines():
    if line:
        decoded = line.decode()
        if decoded.startswith("data: "):
            event = json.loads(decoded[6:])
            t = event.get("type")
            if t == "reasoning_streaming":
                print(event.get("content", ""), end="", flush=True)
            elif t == "reasoning_ended":
                print("\n---------Reasoning Ended, Response Started---------")
            elif t == "content_streaming":
                print(event.get("content", ""), end="", flush=True)

​
Google (Gemini 2.5)

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"budget_tokens": 8192},
        "llm_provider": "google",
        "model_name": "gemini-2.5-pro",
        "stream": True
    },
    stream=True
)
for line in response.iter_lines():
    if line:
        decoded = line.decode()
        if decoded.startswith("data: "):
            event = json.loads(decoded[6:])
            t = event.get("type")
            if t == "reasoning_streaming":
                print(event.get("content", ""), end="", flush=True)
            elif t == "reasoning_ended":
                print("\n---------Reasoning Ended, Response Started---------")
            elif t == "content_streaming":
                print(event.get("content", ""), end="", flush=True)

​
Google (Gemini 3)

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "google",
        "model_name": "gemini-3.1-pro-preview",
        "stream": True
    },
    stream=True
)
for line in response.iter_lines():
    if line:
        decoded = line.decode()
        if decoded.startswith("data: "):
            event = json.loads(decoded[6:])
            t = event.get("type")
            if t == "reasoning_streaming":
                print(event.get("content", ""), end="", flush=True)
            elif t == "reasoning_ended":
                print("\n---------Reasoning Ended, Response Started---------")
            elif t == "content_streaming":
                print(event.get("content", ""), end="", flush=True)

​
xAI

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"effort": "high"},
        "llm_provider": "xai",
        "model_name": "grok-4.3",
        "stream": True
    },
    stream=True
)
for line in response.iter_lines():
    if line:
        decoded = line.decode()
        if decoded.startswith("data: "):
            event = json.loads(decoded[6:])
            t = event.get("type")
            if t == "reasoning_streaming":
                print(event.get("content", ""), end="", flush=True)
            elif t == "reasoning_ended":
                print("\n---------Reasoning Ended, Response Started---------")
            elif t == "content_streaming":
                print(event.get("content", ""), end="", flush=True)

​
OpenRouter

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {"max_tokens": 4096},
        "llm_provider": "openrouter",
        "model_name": "minimax/minimax-m1",
        "stream": True
    },
    stream=True
)
for line in response.iter_lines():
    if line:
        decoded = line.decode()
        if decoded.startswith("data: "):
            event = json.loads(decoded[6:])
            t = event.get("type")
            if t == "reasoning_streaming":
                print(event.get("content", ""), end="", flush=True)
            elif t == "reasoning_ended":
                print("\n---------Reasoning Ended, Response Started---------")
            elif t == "content_streaming":
                print(event.get("content", ""), end="", flush=True)

​
Cerebras

response = requests.post(
    "https://app.backboard.io/api/threads/messages",
    headers=headers,
    json={
        "thread_id": thread_id,
        "content": "A driver was going the wrong way down a one-way street. He passed several police officers, but they did not stop him. Why? Think step by step.",
        "thinking": {},
        "llm_provider": "cerebras",
        "model_name": "z-ai/glm-4.7",
        "stream": True
    },
    stream=True
)
for line in response.iter_lines():
    if line:
        decoded = line.decode()
        if decoded.startswith("data: "):
            event = json.loads(decoded[6:])
            t = event.get("type")
            if t == "reasoning_streaming":
                print(event.get("content", ""), end="", flush=True)
            elif t == "reasoning_ended":
                print("\n---------Reasoning Ended, Response Started---------")
            elif t == "content_streaming":
                print(event.get("content", ""), end="", flush=True)

​
Check Model Support

import requests

models = requests.get(
    "https://app.backboard.io/api/models",
    headers={"X-API-Key": "YOUR_API_KEY"},
    params={"supports_thinking": True, "model_type": "llm"}
).json()

for m in models["models"]:
    print(f"{m['provider']}/{m['name']}")

See Models for details.