Claude Sonnet 5 API: Endpoint, Model ID, and Python Example

Set up the Claude Sonnet 5 API on OurToken. Copy the exact Messages endpoint, model ID, and pricing, then run a cURL test and call Sonnet 5 from Python.

O
OurToken Team//13 min
Claude Sonnet 5 API: Endpoint, Model ID, and Python Example

The Claude Sonnet 5 API is the cheapest entry into Anthropic's 1M-token context class: Sonnet 5 handles long documents, agentic coding, and tool loops at $0.80 per million input tokens and $4.00 per million output tokens on OurToken — 40% of the official comparison price.

A lower price only matters if the request actually reaches the model. A valid key can still fail with 401, 404, or model_not_found when an application sends it to the wrong path, uses a catalog-style model name, or parses the response as an OpenAI choices object. This guide gets one real request working end to end: the exact endpoint and model ID, a cURL smoke test, a Python client, token cost math, and a Sonnet 5 vs Opus 5 routing decision. The current route is:

Base URL:     https://api.ourtoken.ai/v1
Full URL:     https://api.ourtoken.ai/v1/messages
Model ID:     claude-sonnet-5
Auth header:  Authorization: Bearer YOUR_API_KEY

The configuration follows the current Claude Sonnet 5 model page, and the request and response shapes follow the public Anthropic Messages API reference.

Verification status: The route, model ID, context window, output cap, and prices were checked against the OurToken Claude Sonnet 5 model page and the launch documentation on 2026-09-10. The examples are documentation-verified and require your own OurToken API key for live execution. Confirm current prices on the live model page before budgeting production traffic.

Claude Sonnet 5 API Route and Configuration Values

Claude Sonnet 5 on OurToken uses the Anthropic Messages API shape — the /messages path, a messages array, a top-level system field, and typed content blocks in the response — authenticated with the same Authorization: Bearer header as every other OurToken route. It does not use the Anthropic-native x-api-key or anthropic-version headers.

Keep the four configuration values separate in environment variables or server-side config, so switching models later never requires editing request code.

Exact values to copy

SettingCurrent OurToken valueWhat it controls
API key sourceOurToken API KeysCreates the Bearer credential used by the gateway
SDK base URLhttps://api.ourtoken.ai/v1Root URL passed to an HTTP client or config file
Full API endpointhttps://api.ourtoken.ai/v1/messagesURL used by cURL or raw HTTP requests
Model IDclaude-sonnet-5Selects the Claude Sonnet 5 route
Auth headerAuthorization: Bearer YOUR_API_KEYAuthenticates the request
Required body fieldsmodel, messages, max_tokensMinimum Messages API request
Response text pathcontent[].textMessages API response parser

The difference between a base URL and a full endpoint is the most common setup mistake. cURL does not construct paths for you; it must use the complete /v1/messages URL. The second common mistake is reaching for the OpenAI SDK: this route does not return a choices array, so client.chat.completions.create will not parse the response even if the request reaches the server.

The Messages API shape differs from Chat Completions in four places that break a naive port:

  1. system is a top-level parameter, not a message with role: "system".
  2. max_tokens is required on every request, not optional.
  3. The response content is an array of typed blocks, not a single string.
  4. Usage is reported as input_tokens and output_tokens, not prompt_tokens and completion_tokens.

Model ID mistakes to avoid

The exact model value is claude-sonnet-5. If you see model_not_found, check this value first before changing any other code.

Wrong valueWhy it fails
Claude Sonnet 5Display name, not an API model ID
claude-sonnet-5.0Adds a version suffix that does not exist
anthropic/claude-sonnet-5Catalog-style path, not the API model ID
claude-5-sonnetReorders the model name
claude-sonnet-4-6Previous generation route, a different model

Get and Test a Claude Sonnet 5 API Key

An API key authenticates application requests. It is not an Anthropic Console login, a model ID, or a browser session. Create or manage the credential on the OurToken API Keys page; the protected page may redirect to login before key management is available.

Store the key as an environment variable

On macOS or Linux:

export OURTOKEN_API_KEY="paste-your-key-locally"

On Windows PowerShell:

$env:OURTOKEN_API_KEY = "paste-your-key-locally"

Do not paste the key into frontend JavaScript, a public repository, a shared notebook, a screenshot, or a bug report. Treat it like a production password: server-side storage, scoped access, and rotation on suspicion of exposure.

cURL smoke test

Start with a tiny request. It proves the key, endpoint, model ID, and body shape before you test a real coding or agent prompt.

curl -sS https://api.ourtoken.ai/v1/messages \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer ${OURTOKEN_API_KEY}" \
  -d '{
    "model": "claude-sonnet-5",
    "max_tokens": 256,
    "messages": [
      {
        "role": "user",
        "content": "Give me a short checklist for reviewing a pull request."
      }
    ]
  }'

A successful response contains a top-level type of message, a role of assistant, a content array, the model ID, a stop reason, and a usage object. The generated words will vary.

{
  "id": "msg_redacted",
  "type": "message",
  "role": "assistant",
  "model": "claude-sonnet-5",
  "content": [
    {
      "type": "text",
      "text": "1. Check the intent.\n2. Review risky code paths.\n3. Confirm tests and rollback."
    }
  ],
  "stop_reason": "end_turn",
  "usage": {
    "input_tokens": 24,
    "output_tokens": 28
  }
}

This is an illustrative response shape, not a captured private response. The parser point: read assistant text from content[].text, never from choices[0].message.content.

PowerShell smoke test

$payload = @{
  model = "claude-sonnet-5"
  max_tokens = 256
  messages = @(
    @{
      role = "user"
      content = "Give me a short checklist for reviewing a pull request."
    }
  )
} | ConvertTo-Json -Depth 5

curl.exe "https://api.ourtoken.ai/v1/messages" `
  -H "Content-Type: application/json" `
  -H "Authorization: Bearer $env:OURTOKEN_API_KEY" `
  --data-raw $payload

If cURL fails, fix the raw request first. If raw HTTP works but an SDK or app integration fails, the bug is in SDK headers, path construction, response parsing, or model configuration.

Claude Sonnet 5 API Pricing and Cost per Request

The current model page lists Claude Sonnet 5 at 40% of the official comparison price. Prices were checked on 2026-09-10 and should be confirmed on the live page before budgeting.

Token typeOurToken priceOfficial comparison price
Input$0.80 / 1M tokens$2.00 / 1M tokens
Output$4.00 / 1M tokens$10.00 / 1M tokens
Cache write$1.00 / 1M tokens$2.50 / 1M tokens
Cache read$0.08 / 1M tokens$0.20 / 1M tokens

The context window is 1M tokens with up to 128K output tokens, so the pricing has real consequences at both ends:

  • A single request that fills the entire 1M-token input window costs $0.80 before output tokens, compared with $2.00 on Claude Opus 5.
  • An agentic loop that runs 200 steps per task multiplies per-step cost, which is exactly where the $0.80/$4.00 rate compounds into savings.
  • Cache reads at $0.08/M reward stable system prompts: repeated context costs a tenth of the uncached input rate.

Worked cost examples

These are arithmetic illustrations of the prices above, not measured billing. Confirm how your dashboard reports cached versus uncached input before reconciling invoices.

Uncached agent step. A request sends 20,000 input tokens and receives 2,000 output tokens:

input:  20,000 / 1,000,000 × $0.80 = $0.0160
output:  2,000 / 1,000,000 × $4.00 = $0.0080
total:                             = $0.0240

Cached agent step. The same request with a stable system prompt, where 18,000 of the 20,000 input tokens are served from cache at $0.08/M:

fresh input: 2,000 / 1,000,000 × $0.80 = $0.0016
cache read: 18,000 / 1,000,000 × $0.08 = $0.0014
output:      2,000 / 1,000,000 × $4.00 = $0.0080
total:                                 = $0.0110

Caching cuts that step's cost by more than half, and the effect compounds across every repeated system prompt in a long-running agent.

Cost estimator in Python

SONNET_5_PRICE_PER_MTOK = {
    "input": 0.80,
    "output": 4.00,
    "cache_write": 1.00,
    "cache_read": 0.08,
}

def sonnet_5_request_cost(usage: dict) -> float:
    """Estimate one request's cost from Messages API usage fields."""
    return (
        usage.get("input_tokens", 0) * SONNET_5_PRICE_PER_MTOK["input"] / 1_000_000
        + usage.get("output_tokens", 0) * SONNET_5_PRICE_PER_MTOK["output"] / 1_000_000
        + usage.get("cache_creation_input_tokens", 0) * SONNET_5_PRICE_PER_MTOK["cache_write"] / 1_000_000
        + usage.get("cache_read_input_tokens", 0) * SONNET_5_PRICE_PER_MTOK["cache_read"] / 1_000_000
    )

Pass the usage object from the API response and log the result alongside the model ID and request ID. That pairing is what makes a monthly bill explainable.

Claude Sonnet 5 API Python Example

Use a Python HTTP client when you need exact control over the Authorization: Bearer header. The official Anthropic SDK is designed for Anthropic-native x-api-key authentication, while the current OurToken page documents Bearer auth. Unless you have verified the SDK against a live OurToken key, httpx is the safer first client.

Install the dependency:

python -m pip install --upgrade httpx

Single request with cost logging

import os

import httpx

BASE_URL = "https://api.ourtoken.ai/v1"
API_KEY = os.environ["OURTOKEN_API_KEY"]

payload = {
    "model": "claude-sonnet-5",
    "max_tokens": 512,
    "system": "You are a concise senior software engineering assistant.",
    "messages": [
        {
            "role": "user",
            "content": "Explain how to review a database migration safely.",
        }
    ],
}

response = httpx.post(
    f"{BASE_URL}/messages",
    headers={
        "Content-Type": "application/json",
        "Authorization": f"Bearer {API_KEY}",
    },
    json=payload,
    timeout=60.0,
)
response.raise_for_status()
data = response.json()

text_blocks = [
    block["text"]
    for block in data.get("content", [])
    if block.get("type") == "text" and "text" in block
]
print("\n".join(text_blocks))

usage = data.get("usage", {})
print(
    {
        "model": data.get("model"),
        "stop_reason": data.get("stop_reason"),
        "input_tokens": usage.get("input_tokens", 0),
        "output_tokens": usage.get("output_tokens", 0),
        "cache_creation_input_tokens": usage.get("cache_creation_input_tokens", 0),
        "cache_read_input_tokens": usage.get("cache_read_input_tokens", 0),
    }
)

The parser loops through text blocks instead of assuming the first block is text. That matters once tools or extended features are enabled, because Claude responses can then include other typed blocks.

Basic response assertions

assert data["type"] == "message"
assert data["role"] == "assistant"
assert data["model"] == "claude-sonnet-5"
assert isinstance(data.get("content"), list)
assert data.get("usage", {}).get("input_tokens") is not None

Use assertions in smoke tests, not as your production error strategy. In production, convert them into structured validation errors, log the route, and return a safe application-level message.

Multi-turn request

The Messages API is stateless. Send the conversation history again for a follow-up, preserving assistant content as blocks rather than flattening it into plain text, especially if you later enable tools.

messages = [
    {"role": "user", "content": "List three risks in a database migration."}
]

first = httpx.post(
    f"{BASE_URL}/messages",
    headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
    json={"model": "claude-sonnet-5", "max_tokens": 256, "messages": messages},
    timeout=60.0,
)
first.raise_for_status()
first_data = first.json()

messages.append({"role": "assistant", "content": first_data["content"]})
messages.append({"role": "user", "content": "Turn that into a release checklist."})

second = httpx.post(
    f"{BASE_URL}/messages",
    headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"},
    json={"model": "claude-sonnet-5", "max_tokens": 512, "messages": messages},
    timeout=60.0,
)
second.raise_for_status()
print(second.json()["content"][0]["text"])

For debugging, log request IDs, model IDs, stop reasons, and token counts rather than raw customer content, and keep raw transcripts only if your privacy policy and data-retention plan allow it.

Claude Sonnet 5 vs Claude Opus 5: Which API Route to Use

Both Claude 5 models share the same Messages API route, the same 1M-token context window, the same 128K output cap, and the same Bearer authentication. For the Opus 5 counterpart, see the Claude Opus 5 model page. The model ID is the only code change. The price and the reasoning depth are what differ.

DimensionClaude Sonnet 5Claude Opus 5
Model IDclaude-sonnet-5claude-opus-5
Input price$0.80 / 1M$2.00 / 1M
Output price$4.00 / 1M$10.00 / 1M
Cache read$0.08 / 1M$0.20 / 1M
Context window1M tokens1M tokens
Max output128K tokens128K tokens
Share of official price40%40%
Strongest fitAgentic coding, tool loops, high-volume professional workDeep reasoning, long-horizon agents, hardest software engineering

Route by workload:

WorkloadRoute toWhy
PR review, test generation, documentationSonnet 5High volume multiplies the $0.80/$4.00 rate
Long-document ingestion at 1M classSonnet 5A full-context input costs $0.80 vs $2.00
Agent tool loops (most steps)Sonnet 5Per-step cost compounds across hundreds of calls
Architecture decisions, hardest debuggingOpus 5Deeper reasoning justifies 2.5× input cost
Escalation after a failed Sonnet stepOpus 5Pay the premium only on the difficult tail

A practical pattern is escalation routing, where the same client and parser serve both models:

Agent step
  -> classify task difficulty (static rules or a cheap classifier call)
  -> default route:      claude-sonnet-5   ($0.80/M in, $4.00/M out)
  -> escalation route:   claude-opus-5     ($2.00/M in, $10.00/M out)
  -> both via POST https://api.ourtoken.ai/v1/messages
  -> same Bearer key, same parser — the model ID is the only change

For stacks standardized on OpenAI-shaped requests, OurToken also exposes GPT-6 Astra with a 1,050K context window through a Responses API route — see the GPT-6 Astra model page — but Claude 5 models remain on the Messages shape shown throughout this guide.

If you need the Messages API pattern applied to the previous generation with full troubleshooting detail, the Claude Opus 4.8 API key setup guide walks the same route with 200K-class context values.

Troubleshooting Claude Sonnet 5 API Errors

Most first-request failures are configuration, not quota. Check in this order: auth header, full URL, model ID, required fields, response parser.

SymptomLikely causeFix
401 unauthorizedx-api-key header, or missing/wrong keySend Authorization: Bearer YOUR_API_KEY
404 not foundBase URL used without /messages, or missing /v1Use the full https://api.ourtoken.ai/v1/messages URL
model_not_foundWrong model value (dots, catalog path, reordered name)Use exactly claude-sonnet-5
400 validation errorMissing required max_tokensInclude max_tokens on every request
Parser exceptionReading choices[0].message.contentRead text from content[].text blocks
Empty text outputStop reason consumed the turn (e.g., tool use)Inspect stop_reason and handle non-text blocks

Two habits make the rest easy. First, keep the cURL smoke test in your repo so "SDK broken" claims can be checked against raw HTTP in seconds. Second, log stop_reason and the full usage object on every call: cost surprises and truncation surprises are both visible there before users report them.

Conclusion

The Claude Sonnet 5 API setup reduces to four verified values: the https://api.ourtoken.ai/v1/messages endpoint, a Bearer-authenticated key from the OurToken API Keys page, the model ID claude-sonnet-5, and a parser that reads content[].text. Everything else — caching, cost tracking, Sonnet-to-Opus escalation — builds on that same request shape without code changes beyond the model ID.

Create a key on the OurToken API Keys page, point your client at the endpoint above, and start with the cURL smoke test; the same Python client then covers Sonnet 5, Opus 5, and the rest of the catalog by changing one model value.

FAQ

What is the Claude Sonnet 5 context window?

Claude Sonnet 5 supports a 1M-token input context window with up to 128K output tokens per response, per the current OurToken model page. That is the same context class as Claude Opus 5.

What is the exact Claude Sonnet 5 model ID?

claude-sonnet-5 — lowercase, hyphenated, no version suffix. Values like claude-sonnet-5.0, anthropic/claude-sonnet-5, or Claude Sonnet 5 are display or catalog forms and will fail with model_not_found.

Is the Claude Sonnet 5 API OpenAI-compatible?

No. The current OurToken Claude Sonnet 5 route uses the Anthropic Messages API shape (/v1/messages, top-level system, typed content blocks) with Bearer authentication. It is not a /chat/completions route, and OpenAI SDK parsers will not read its responses. Check the model page for the recommended route before integrating.

How much does the Claude Sonnet 5 API cost?

On OurToken: $0.80 per million input tokens, $4.00 per million output tokens, $1.00 per million cache-write tokens, and $0.08 per million cache-read tokens — 40% of the official comparison price of $2.00/$10.00/$2.50/$0.20. Confirm current prices on the live model page before budgeting.

Can I use the official Anthropic SDK with this route?

The official SDK is built around Anthropic-native x-api-key headers, while the OurToken route documents Authorization: Bearer. Verify the SDK against a live OurToken key before adopting it; the httpx examples in this guide are the safer starting point because they control the auth header explicitly.